首页 > 技术文章 > UVA11027_Palindromic Permutation

lochan 2014-07-15 11:30 原文

此题不错。给你一些字字符,要求你用这些字符构成一个回文串,求字典序第k大的回文串。

首先通过给定的字符,我们可以直接判断能否构成回文串(奇数的字符不超过一种),其次可以统计每个字符在回文串的左边应该出现多少次。

然后从左到右判断每一位应该放那个字母,一边放置一遍更新即可。

我仅判断奇数次的个数为奇偶就ac了,输出的时候只输出了一个,如果有三个呢? 哈哈, 数据太水了。

 

召唤代码君:

 

 

#include <iostream>
#include <cstdio>
#include <cstring>
typedef long long ll;
using namespace std;

int t[26],c[26],n,T,cas=0,tot,pos;
char s[55],ans[55];
ll P[20];
bool flag;

ll count()
{
    ll sum=0,cur=1;
    for (int i=0; i<26; i++)
        sum+=t[i],cur*=P[t[i]];
    return P[sum]/cur;
}

int main()
{
    P[0]=1;
    for (int i=1; i<20; i++) P[i]=P[i-1]*i;
    scanf("%d",&T);
    while (T--)
    {
        flag=true;
        scanf("%s%d",s,&n);
        memset(t,0,sizeof t);
        pos=-1;
        tot=0;
        for (int i=0; s[i]; i++) t[s[i]-'a']++;
        for (int i=0; i<26; t[i]/=2,tot+=t[i],i++)
            if (t[i]&1) 
            {
                if (pos==-1) pos=i;
                    else flag=false;
            }
        printf("Case %d: ",++cas);
        if (!flag || count()<n)
        {
            puts("XXX");
            continue;
        }
        for (int i=1; i<=tot; i++)
        {
            
            for (int j=0; j<26; j++)
            {
                if (t[j]<=0) continue;
                t[j]--;
                ll tmp=count(); 
                if (n<=tmp)
                {
                    c[i]=j+'a';
                    break;
                }
                t[j]++,n-=tmp;
            }
        }
        for (int i=1; i<=tot; i++) printf("%c",c[i]);
        if (pos!=-1) printf("%c",(char)('a'+pos));
        for (int i=tot; i>=1; i--) printf("%c",c[i]);
        printf("\n");
    }
    return 0;
}

 

推荐阅读