http://poj.org/problem?id=1850
首先应该判断一下给出的字符串是否为升序,否则答案为0.
对于长度为L的一串,我们首先应该加上比它短的串的个数,然后再算它是长度为L的里面的第几个。
在算长度为len的串的个数的时候,因为都是升序的,特定的几个字符组成的串没有重复,所以我们可以
用组合数来算,个数为C(26,len)。
然后再算它是长度为L的串的第几个时,一位一位地算,举个例子吧。
c f j l 对于这个串,s[0]为c,那么我们先把长度为四以a~b开头的个数加上,以a开头的为C(25,3)个,
以b开头的为C(24,3)个;然后我们再算以c开头,以s[0]+1~e为第二位的个数,即C(22,2)+C(21,2)……
以此类推,当我们算到最后一位之后,以为我们算的都是它前面的个数,所以最后答案再加 1 。
里面有很多细节,具体看代码吧。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define LL long long
using namespace std;
char s[50];
LL ans,L;
LL yh[30][30];
void work()
{
for(int i=0;i<L;i++)
{
int d;
if(i-1>=0) d=s[i-1]-'a'+2;
else d=1;
for(int j=d;j<s[i]-'a'+1;j++)
{
ans+=yh[26-j][L-i-1];
}
}
}
int main()
{
for(int i=0;i<=26;i++) yh[i][i]=1,yh[i][0]=1;
for(int i=1;i<=26;i++) for(int j=1;j<=i;j++)
yh[i][j]=yh[i-1][j]+yh[i-1][j-1];
cin>>s;L=strlen(s);
for(int i=1;i<L;i++)
if(s[i]<s[i-1]) {cout<<"0";return 0;}
for(int i=1;i<L;i++) ans+=yh[26][i];
work();
ans+=1;
printf("%lld",ans);
return 0;
}