蓝桥杯——排列序数(C++STL解决)

排列序数

如果用a b c d这4个字母组成一个串,有4!=24种,如果把它们排个序,每个串都对应一个序号:
abcd 0
abdc 1
acbd 2
acdb 3
adbc 4
adcb 5
bacd 6
badc 7
bcad 8
bcda 9
bdac 10
bdca 11
cabd 12
cadb 13
cbad 14
cbda 15
cdab 16
cdba 17

现在有不多于10个两两不同的小写字母,给出它们组成的串,你能求出该串在所有排列中的序号吗?

输入格式
一行,一个串。

输出格式
一行,一个整数,表示该串在其字母所有排列生成的串中的序号。注意:最小的序号是0。

输入: bdca
输出: 11
输入: cedab
输出: 70

思路
由题中给出的数据分析得知,当只有四位字母时,a、b、c、d开头的序列中都有六种形式,即当第一个字母固定时,其余三个就有3!种组合方法,同样的,当第二个字母也固定时,还剩下两个字母,此时有2!种组合方法。由此可得,把这个题看成时组合题来做。
拿bdca为例,设n1~n4为bdca上的位数,第一个字母为b,说明bdca至少大于6,即令n1=6。第二个字母为d,由于不可以重复,剩下的a、c、d里d应该是最大的,且每个字母有两种组合,所以n2=4。之后还剩两个字母,第三个字母为c,c比a大,c和a都各有一种组合,所以n1=1。此时sum=n1+n2+n3=11,输出11。

发现此规律后,设sum为要输出的数,输入的字符串有n位,string str=“abcdefghij”(不超过十位),设k=第i位数在str中的位置
对于第一位有:
x1=(n-1)!*k,并且在str中移除第一位数
sum+=x1
对于第二位有:
x2=(n-2)!*k,并且在str中移除第二位数
sum+=x2

对于第n位数有
xn=(n-n)!*k
sum+=xn;
此时sum即为输出的数

由以上得,用STL中的string便可以解决该问题,将求和部分分成两个问题,第一个问题为(n-i)的阶乘,第二个问题为第i位在str中的位置。再加上如何将第i位数移除,共三个问题,解决这三个问题答案就出来了。对于第一个问题,相信大家都会,此处不过于详解。对于第二个问题,可以自定以一个函数,该函数返回第i位在str中的位置。最后一个问题,可以用erase将第i位在str中删除。
最后,上代码:

#include 
#include 
#include 

using namespace std;

int FindIndex(char op,string str){
	int i;
	for(i=0;i<str.length();i++)
		if(op==str[i])
			break;
	return i;
} 

int main()
{
	string str1,str2="abcdefghij";
	int i,sum,j,n,m,k;
	cin >>str1;
	sum=0;
	n=str1.length();
	for(i=1;i<=n;i++){
		m=1;
		for(j=1;j<=n-i;j++)
			m*=j;
		k=FindIndex(str1[i-1],str2);
		sum+=m*k;
		str2.erase(str2.begin()+k);
	}
	printf("%d",sum);
	return 0;
}

你可能感兴趣的:(蓝桥杯)