poj 1850 组合计数
题意:给一个字符串 S,长度<=10,其中的字母按升序排列。长度小的字符串比大的字符串靠前,长度相同按字典序排列,问 S 排第几个。
a - 1
b - 2
...
z - 26
ab - 27
...
az - 51
bc - 52
...
vwxyz - 83681
分析:字母按升序排列,则选出若干字母,其排列唯一。先求长度len,比它短的字符串有C(26,1) + C(26,2) +...+C(26,len-1) 个。
对于长度相同的字符串,设S=“ b d f h t ”,则前四位和 S 相同,最后一位小于 't' 并且大于 'h' 的有C('z'-'h',1) - C('z'-'t'+1,1)种情况。
前三位和S相同,后两位小于S的有C('z'-'f', 2) - C('z'-'h'+1, 2)种。
......
const int maxn = 27; LL a[maxn][maxn]; void init(){ FOR(i,0,maxn) { a[i][0]=1; a[i][1]=i; FOE(j,2,i) a[i][j] = a[i-1][j] + a[i-1][j-1]; } } int main(){ #ifndef ONLINE_JUDGE //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); #endif init(); string s; cin>>s; int l = s.length(); FOR(i,0,l-1) if(s[i]>=s[i+1]) {cout<<0<<endl;return 0;} LL cnt = 0; FOR(i,1,l) cnt+=a[26][i]; FOR(i,1,l){ char c = s[l-i], c1 = s[l-i-1]; cnt += a['z'-c1][i] - a['z'-c+1][i]; } cnt += a[26][l] - a['z'-s[0]+1][l]; cout<<cnt+1<<endl; return 0; }