今天的数论测试的题目。我只写出了这一题。
对数学中的组合数的求法记得更深了:
void get() //组合数的求法
{
int i,j;
for( i=0;i<=26;i++)
for( j=0;j<=i;j++)
{
if(j==0||i==j)
c[i][j]=1;
else c[i][j]=c[i-1][j]+c[i-1][j-1];
}
}
这里用到组合数的一个很关键的思想就是: 如果有n身高不同的人,要选m个人从高到低站成一排,有多少种排法?
其实就是C[n][m]个,因为从n个人里选出m个后,他们的站位就已经确定了。
so,对这题,我就讲下求的过程吧,拿s=bdg这个字符串做例子。首先,s的长度len=3
已经是3位的,因为所谓的code是从a增到z再增到ab再增到yz再增到bdg的,即先从1位增到2位再增到3位的。
那么a增到z,code量是26个字母里面选1个,ab增到yz,code量是26个字母里选两个。
然后要计算yz到bdg的过程中有多少code量。
bdg的前面是经过a_ _的。那么a开头的3位有多少个呢?就是25个字母里选2个。因为空格里的字母不能小于等于a。,所以不会包含a。
然后看第2位,是一个d,d和b之间有个c,那么还需要计算c_有多少个,是23个里面选1个
然后看g,g和d之间有e和f。故就是1+1.
所以答案等于C[26][1]+C[26][2]+C[25][2] +C[23][1]+1+1
#include<iostream>
#include<string>
#include<cmath>
using namespace std;
int n,c[27][27],a[12];
void get() //组合数的求法
{
int i,j;
for( i=0;i<=26;i++)
for( j=0;j<=i;j++)
{
if(j==0||i==j)
c[i][j]=1;
else c[i][j]=c[i-1][j]+c[i-1][j-1];
}
}
int main()
{
int i,j,ans;
char s[12];
get();
cin>>s+1;
int len=strlen(s+1);
for(i=2;i<=len;i++)
if(s[i]<=s[i-1])
{
cout<<"0"<<endl;
return 0;
}
ans=0;
for(i=1;i<=len-1;i++) //假如有3位,先把1位和2位的总数加起来
ans+=c[26][i];
s[0]='a'-1;
for(i=1;i<=len;i++)
{ //每次计算他前面的,如果是bf,b只计算a,f只计算cde
//c[25-j][len-i]
for(j=s[i-1]-'a'+1;j<s[i]-'a';j++)
{
ans+=c[25-j][len-i];
}
}
cout<<ans+1<<endl;
}