题目意思:给出一串字符串问按照文中的序号排,序号是多少。
思路:先计算出n位字符,一共有多少种情况,再减去比这个字符大的情况种数。
主要步骤一:
长度为一的字符串有26种(a,b,c,...,z) C(26,1)
长度为二的字符串有:
以a开头的25种(ab,ac,ad,...,az) C(25,1)
以b开头的24种(bc,bd,...,bz) C(24,1)
... ...
以y开头的有1种,yz C(1,1)
一共 C(25,1)+C(24,1)+...+C(1,1)=1+2+3+..+25=25*26/2=C(26,2)
其实这里有一个重要的组合数公式:
长度为三的自然有C(26,3)种
那只要一个循环就可以将每一位一共的情况计算出来。
主要步骤二:
减去每一位比它大的字符串。这里可以想象成拿小球了。
例如: abc
计算第一位 abc 比a大的字符有25个,只要从中选三个字符组合就比它大 所以是C(25,3)
计算第二位 abc 比b大的字符有24个,只要从中选两个构成(axx)就比它大,所以是C(24,2)
计算第二位 abc 比c大的字符有23个,只要从中选一个构成(abx)就比它大,所以是C(23,1)
这样就计算出来序号了。但是 注意不可法的情况输出0
下面是poj1850的代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; int c[30][30]; void init()//组合数打表 { c[0][0]=1; for(int i=1;i<30;i++) { c[i][0]=1; for(int j=1;j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1]; } } int main() { string s; init(); cin>>s; int len=s.length(); int res=0; for(int i=1;i<len;i++)//不合法情况 { if(s[i-1]>=s[i]) { cout<<res<<endl; return 0; } } for(int i=1;i<=len;i++)//加每一位情况 res+=c[26][i]; for(int i=0;i<len;i++)//减大于字符串的情况 res-=c[26-(s[i]-'a'+1)][len-i]; cout<<res<<endl; return 0; }
poj1496:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; int c[30][30]; void init() { c[0][0]=1; for(int i=1;i<30;i++) { c[i][0]=1; for(int j=1;j<=i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1]; } } int main() { string s; init(); while(cin>>s) { int len=s.length(); int res=0,flag=0; for(int i=1;i<len;i++) { if(s[i-1]>=s[i]) { cout<<res<<endl; flag=1; } } if(flag) continue; for(int i=1;i<=len;i++) res+=c[26][i]; for(int i=0;i<len;i++) res-=c[26-(s[i]-'a'+1)][len-i]; cout<<res<<endl; } return 0; }