Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 9282 | Accepted: 4432 |
Description
The coding system works like this:
• The words are arranged in the increasing order of their length.
• The words with the same length are arranged in lexicographical (辞典编纂的) order (the order from the dictionary).
• We codify (编纂) these words by their numbering, starting with a, as follows:
a - 1
b - 2
...
z - 26
ab - 27
...
az - 51
bc - 52
...
vwxyz - 83681
...
Specify (指定) for a given word if it can be codified according to this coding system. For the affirmative (肯定的) case specify its code.
Input
• The word is maximum 10 letters length
• The English alphabet (字母表) has 26 characters.
Output
Sample Input
bf
Sample Output
55
一种类型的题多做几道,就可以自己想啦~这次一点也没有依靠别人呐~
这个题就是告诉你有一种单词编码,就是把26个字母选取一定的个数按照一定的规则排列成一个单词,每个单词对应一个编号。
规则:
1.单词按照长度递增的顺序排列。
2.相同长度的单词按照字典序排列。
3.编号是这样定义的:
a - 1
b - 2
...
z - 26
ab - 27
...
az - 51
bc - 52
...
vwxyz - 83681
可以看出来每个字符并不能重复。
现在给你一个单词,问你是不是存在与这种编码系统里,如果存在输出序号,如果不存在那么输出0(QAQ,没看到贡献了wa的一发)。
思路:
1.这个编码系统每个字符并不重复,并且每个串都是按照字典序排列,也就是说你可以随意选几个字符,它在这个系统中,每个字符的顺序都是确定了的。
换句话说就是,如果单词的长度是1,那么长度为1的所有单词个数就是C(26:1),以此类推长度为2的所有单词的个数就是C(26:2).....。
那么我们再求给定单词编号的时候可以先把长度为1,2,3,4....(l-1)的个数求出来,然后答案累加。
2.然后就是如何求相同长度下比所给定的串的编码小的个数了。
这时候我们分割
这里我们从第一个字符开始想,首先应当求出比第一个字符小的所有的串的个数,比如说第一个字符是c,那么我们应当求出a....+b....的串的个数,这个不难,因为第一个字符选定以后,后面的字符都没有限制,所以就是从大于第一个字符的所有字符中选取l-1个字符就是。如果我们把字符编号0-25,那么就是C(25-第一个字符编号:l-1)(这个我后面在代码再细说一下)。之后再看第二个字符,如果第二个字符是g,那么我们应当求得是d....+e....+f....,也就是说我们枚举的范围是大于前面一个字符小于当前字符的。计算这个的时候就是C(25-第二个字符编号:l-2) ,然后依次类推即可。
3.求到最后一个字符的时候,按照之前的算法,我们并没有计算最后一个字符的,也就是说我们计算的只是这个单词之前的单词有多少个,所以最后的编号应当是累加和再加一。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN=10+5;
const int inf=0x3f3f3f;
int f(int n,int m)//f函数计算的是C(n:m)
{
int sum=1;
for(int i=1; i<=m; ++i)
{
sum=sum*n/i;
n--;
}
return sum;
}
int sum[MAXN]= {26,325,2600,14950,65780, //这里sum记录的是C(26:i),i从1到10的结果
230230,657800,1562275,3124550,5311735
};
char s[MAXN];
int l;
bool adjust()//这个函数是判断给定的串是不是在这个编码系统里的,编码系统的要求每个字符不重复并且按照字典序排序
{
int i;
for(i=1; i<l; ++i)if(s[i+1]<=s[i])return 0;
return 1;
}
int main()
{
int i,j;
int ans=0;
scanf("%s",s+1);//为了方便直接从s+1读取
l=strlen(s+1);
if(!adjust())puts("0");
else
{
for(i=0; i<l-1; ++i)ans+=sum[i]; //先把长度为0~(l-1)的串的个数求出来
s[0]='a'-1; //为了下面的方便,这里加上一个边界值,第一个默认从字符a开始
for(i=1; i<=l; ++i) //i表示所给的串中的第i个字符
{
for(j=s[i-1]-'a'+1; j<s[i]-'a'; ++j) //j应当是大于前一个字符的字符开始(编码是按照0-25编的),j的末值应当小于当前字符,等于之后应当枚举下一个字符
{
ans+=f(25-j,l-i);//当前字符确定之后应当从比当前字符大的字符里面选取l-i个组成串
}
}
ans++;//我们只是计算了小于当前串的个数,所以要加1
printf("%d\n",ans);
}
return 0;
}