POJ1850-Code 递推数学

题目链接:http://poj.org/problem?id=1850

题目大意:

  按照字典序对升序排列组成的字母进行编号,给出一个长度不超过10的串,求出它的编号是多少?如果无法进行编号则输出0。

题目分析:

  先判断字符串是不是升序的,如果不是升序的则不存在编号,直接输出0即可。

  满足升序要求的,则先根据长度len,把长度小于len的串整个处理一下,再对长度为len的递归求解。

  1.定义长度为i,以字母c开头的串的个数为f[i][c]。很容易看出来:f[i][c]=Σf[i-1][k](k=c+1-->'z'-i+2),解释一下k的取值,因为要求升序,所以以字母c开头的长度为i的串,相当于在长度为i-1的串前面插入一个c,可以插的串必然从c+1开始,直到‘z'-i+2。这个上界是为了满足长度的要求,长度为i-1的串最多只能以‘z'-i+2开头。

  2.在定义f[i][c]的时候,已经看出之中的递推关系了。那么对于长度为len的,按照串的顺序,依次处理如下:

  

for(int i='a';i<s[];i++)//对首字母特殊处理
ans+=f[len][i]; for(int i=;i<len;i++)
for(int j=s[i-]+;j<s[i];j++)//对第i个字母处理。要注意是<s[i]。
ans+=f[len-i][j]; ans++;//串本身的那个1.

  这样就求出解了。

 #include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
int f[]['z'+];
int main()
{
string s;
memset(f,,sizeof(f));
for(int i='a';i<='z';i++)
f[][i]=;
for(int i=;i<=;i++)
for(int c='a';c<='z'-i+;c++)
for(int k=c+;k<='z'-i+;k++)
f[i][c]+=f[i-][k];
while (cin>>s)
{
int len=s.size();
int ans=;
bool ok=;
for(int i=;i<len;i++)
if(s[i]<=s[i-])
{
cout<<<<endl;
ok=;
break;
}
if(ok) continue;
for(int i=;i<len;i++)
for(int c='a';c<='z'-i+;c++)
ans+=f[i][c];
for(int i='a';i<s[];i++)
ans+=f[len][i];
for(int i=;i<len;i++)
for(int j=s[i-]+;j<s[i];j++)
ans+=f[len-i][j];
ans++;
cout<<ans<<endl;
}
return ;
}
上一篇:Lsyncd - 实时文件同步工具(精译)


下一篇:mysql 登录远程数据库 失败