Link: http://vjudge.net/problem/viewProblem.action? Id = 19602
Description: returns a string. Find the nth input string after the permutation. If no input string exists, output "XXX".
Idea: number of combinations.
First, consider when there is a return string. It is very simple. There are no more than one letter with an odd number. And the letter can only be in the middle of the string.
Then we will find that the Lexicographic Order of the input string is the Lexicographic Order of the first half of the string. The problem is converted into a string that calculates the nth Lexicographic Order. So we can try to simulate this process. First, place the smallest letter in the Lexicographic Order in the first position, and then calculate the number of subsequent letters, that is, to fix the number of strings after the first position. Set this number to num. If num> = N, the first position is determined, and the second position is considered. If num <n, the letter in the first position is not suitable, N-= num, replace it with the second letter in the Lexicographic Order and repeat the calculation above. If it is always num <n, there is no solution.
PS. zyy is not good at mathematics. It's a bit cool. Please kindly advise me ~
The following is my implementation:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 using namespace std; 6 #define MaxLen 30 7 int T,N; 8 int Cnt[30],Lit; 9 char str[MaxLen+5],Ans[MaxLen+5]; 10 bool flag; 11 inline int fac(int t) 12 { 13 if(t<=2) 14 return t; 15 int i,Ret=1; 16 for(i=2;i<=t;i++) 17 Ret*=i; 18 return Ret; 19 } 20 inline int Arg() 21 { 22 int i,Sum=0; 23 for(i=1;i<=26;i++) 24 { 25 if(!Cnt[i]) 26 continue; 27 Sum+=Cnt[i]; 28 } 29 Sum=fac(Sum); 30 for(i=1;i<=26;i++) 31 { 32 if(!Cnt[i]) 33 continue; 34 Sum/=fac(Cnt[i]); 35 } 36 return Sum; 37 } 38 void Work(int pos,int n) 39 { 40 int i,Num; 41 for(i=1;i<=26;) 42 { 43 if(!Cnt[i]) 44 { 45 i++; continue; 46 } 47 Cnt[i]--; 48 Num=Arg(); 49 if(Num==0) 50 { 51 Ans[pos]=‘a‘+i-1; 52 return; 53 } 54 else if(Num<n) 55 { 56 Cnt[i]++; 57 i++; 58 n-=Num; 59 } 60 else 61 { 62 Ans[pos]=‘a‘+i-1; 63 Work(pos+1,n); 64 return; 65 } 66 } 67 flag=false; 68 } 69 int main() 70 { 71 int Len,i,JS; 72 scanf("%d",&T); 73 for(int t=1;t<=T;t++) 74 { 75 printf("Case %d: ",t); 76 scanf("%s",str); scanf("%d",&N); 77 Len=strlen(str); Lit=(Len+1)/2; 78 if(Len==1) 79 { 80 if(N==1) 81 printf("%s\n",str); 82 else 83 printf("XXX\n"); 84 continue; 85 } 86 memset(Cnt,0,sizeof(Cnt)); 87 for(i=0;i<Len;i++) 88 Cnt[str[i]-‘a‘+1]++; 89 JS=0; 90 for(i=1;i<=26;i++) 91 { 92 if(Cnt[i]%2) 93 { 94 JS++; 95 Ans[Lit]=‘a‘+i-1; 96 } 97 Cnt[i]/=2; 98 } 99 if(JS>=2)100 {101 printf("XXX\n");102 continue;103 }104 flag=true;105 Work(1,N);106 if(!flag)107 printf("XXX\n");108 else109 {110 for(i=1;i<=Lit;i++)111 printf("%c",Ans[i]);112 if(Lit*2==Len)113 for(i=Lit;i>=1;i--)114 printf("%c",Ans[i]);115 else116 for(i=Lit-1;i>=1;i--)117 printf("%c",Ans[i]);118 printf("\n");119 }120 }121 return 0;122 }View code