uva 11027 Palindromic Permutation

#include <iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
typedef long long ll;

using namespace std;
ll fac[20];
char str[50];
int vis[50];
char ans[50];
int cas = 1;

void cal_fac() //阶乘打表
{
    fac[0] = fac[1] = 1;
    for(int i = 2;i <= 15;i++)
        fac[i] = fac[i-1]*i;
}

void print(int a)
{
    if(a ==0) printf("Case %d: XXX\n",cas++);
    else printf("Case %d: %s\n",cas++,ans);
}

ll calc(int len)//去重复后的组合数
{
    ll ret = fac[len];
    for(int i = 0;i < 26;i++)
        ret/=fac[vis[i]];
    return ret;
}

int main()
{
    int t,n;

    cal_fac();
    scanf("%d",&t);
    while(t--)
    {
       scanf("%s %d",str,&n);
       memset(vis,0,sizeof vis);
       int odd = 0;//奇数字符的个数
       int len = strlen(str);
       int len1 = len/2;
       for(int i = 0;i < len;i++) vis[str[i]-'a']++;
       for(int i = 0;i < 26;i++)
       {
           if(vis[i]%2) {odd++;ans[len1] = i+'a';}
           vis[i]/=2;
       }
       if(odd >1) {print(0);continue;}
       ll tmp = calc(len1);
       if(tmp < n) {print(0);continue;} //所有组合数都达不到n
       for(int i = 0;i < len1;i++) //当前确定第几位
       {
           for(int j = 0;j < 26;j++)
           {
               if(vis[j])
               {
                   vis[j]--;
                   tmp = calc(len1-i-1);//计算固定当前位,后面位数的组合数
                   if(tmp >= n)
                   {
                       ans[i] = j+'a';
                       ans[len-1-i] = j+'a';
                       break;
                   }
                   else //第i位放置j达不到n
                   {
                       n-=tmp;
                       vis[j]++;
                   }
               }
           }
       }
       ans[len] = '\0';
       print(1);
    }
    return 0;
}


你可能感兴趣的:(uva 11027 Palindromic Permutation)