LightOJ 1060-第k个排列【数学+模拟】 难度:***

题意:

Given a string of characters, we can permute the individual characters to make new strings. At first we order the string into alphabetical order. Then we start permuting it.

For example the string ‘abba’ gives rise to the following 6 distinct permutations in alphabetical order.

aabb 1

abab 2

abba 3

baab 4

baba 5

bbaa 6

Given a string, you have to find the nth permutation for that string. For the above case ‘aabb’ is the 1st and ‘baab’ is the 4th permutation.

Input
Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case contains a non empty string of lowercase letters with length no more than 20 and an integer n (0 < n < 231).

Output
For each case, output the case number and the nth permutation. If the nth permutation doesn’t exist print ‘Impossible’.

Sample Input
3
aabb 1
aabb 6
aabb 7
Sample Output
Case 1: aabb
Case 2: bbaa
Case 3: Impossible

题解:

注意:不能使用next_permutation函数来解此题,因为一个一个找一定会超过时间限制。
这个其实是逆康托展开,只不过难度再大一点,因为这里有重复字符。
首先先举无重复字符的例子,比如abcd。当a作为第一个时,一共有(4-1)!种情况,然后和答案进行对比,如果答案<3!则a是第一个字符,若不是则换下一个字符,因为就20个字符所以暴力找就行。
对于有重复字符的,比如abbbccc,当a作为第一个字符后,一共的情况数是6!/(3!×3!) ,对于学过排列组合的朋友们可以写成A66/(A33×A33)其实就是排除相同字符内部排序的影响,再重复上面的操作就行。

代码:

#include<stdio.h>
#include<string.h>
const int word=26;
long long jiecheng(int a)
{
	if(a==0)return 1;
	long long sum=1;
	for(int i=2;i<=a;i++)sum*=i;
	return sum;
}
int main()
{
	int t,n,len,count[word],stalen;
	long long temp,max;
	char ch[22];
	scanf("%d",&t);
	for(int l=1;l<=t;l++)
	{
		for(int i=0;i<word;i++)count[i]=0;
		scanf("%s%d",ch,&n);
		len=strlen(ch);
		max=jiecheng(len);
		for(int i=0;i<len;i++)count[ch[i]-'a']++;
		for(int i=0;i<word;i++)if(count[i])max/=jiecheng(count[i]);
		if(n>max)printf("Case %d: Impossible\n",l);
		else
		{
			printf("Case %d: ",l);
			stalen=len;
			for(int i=0;i<stalen;i++)
			{
				for(int j=0;j<word;j++)
				{
					if(!count[j])continue;
					count[j]--;
					temp=jiecheng(len-1-i);
					for(int k=0;k<word;k++)if(count[k])temp/=jiecheng(count[k]);
					if(temp>=n)
					{
						printf("%c",'a'+j);
						break;
					}
					else
					{
						count[j]++;
						n-=temp;
					}
				}
			}
			printf("\n");
			max=0;
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_42921101/article/details/104322128