题干:
Transmitting and memorizing information is a task that requires different coding systems for the best use of the available space. A well known system is that one where a number is associated to a character sequence. It is considered that the words are made only of small characters of the English alphabet a,b,c, ..., z (26 characters). From all these words we consider only those whose letters are in lexigraphical order (each character is smaller than the next character).
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 only line contains a word. There are some constraints:
• The word is maximum 10 letters length
• The English alphabet has 26 characters.
Output
The output will contain the code of the given word, or 0 if the word can not be codified.
Sample Input
bf
Sample Output
55
题目大意:
按一定规则编纂了字典序:
字典中的各字符串中的字母保证严格按升序排列。 长度小的一定在长度大的前面,长度相同时,按照真正的字典序。
给出一个字符串,求该字符串在字典中的编号,若字典中没有(字母不按升序排)则输出0。
解题报告:
一个题解:
对于不同的小写字母,严格升序组成的一组序列,分别代表从1~n的数值。
这题关键是求组合的数值C。对于方法,并不是太难,分两种情况
1.当长度小于给出的字符串L时,对于字符串长度为1的字符串总共代表的数字的量就是C(26,1),对于长度为2的字符串总共代表的数字的量就是C(26,2),一次类推,直到C(26,L-1)。
2.对于长度等于L的,从最开头的字符s[0]开始,对于比这个字符严格小的,如果有一个,我们可以有C('z'-s[0], L-1)个,'z'-s[0] 是因为题意已经说明该字符串每个位置是严格递增的。如果在这个位置,还能找到别s[0]严格小的,则再加上。
再遍历到后面的字符s[i],对于比这个字符严格小的,我们依然可以找到C('z'-s[0], L-i-1)个。一直到最后一个字符,这样,所有结果的总和,就是结果。
对于1中的原理如下:
以两位的串为例,有ab~az,bc~cz,……那么有组合数
递推出这个公式,需要结合组合里的一个很常用的式子
后面的依此类推。有大佬也指出,既然你是升序,那么只要你有几位,你就选几个出来,那么它的严格升序排列只有一种,所以就是C(26,L),就是在长度为L下的所有组合数。
然后利用上面的式子进行递推,求出所有的26以内的所有组合数,再直接利用求结果即可。
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
ll C[33][33];
ll n,ans;
char s[33];
int main()
{C[0][0]=1;for(int i = 1; i<=30; i++) {C[i][0] = 1;for(int j = 1; j<=30; j++) {C[i][j] = C[i-1][j] + C[i-1][j-1];}}while(~scanf("%s",s)) {ll ans = 0;int len = strlen(s);bool flag = 1;for(int i = 0; i<len-1; i++) {if(s[i] >= s[i+1]) {flag = 0;break;}}if(flag == 0) {puts("0");continue;}//之前长度的 for(int i = 1; i<len; i++) {ans += C[26][i];}//当前字符开始计算 for(int i = 0; i<len; i++) {char cur;if(!i) cur = 'a';else cur = s[i-1]+1;while(cur < s[i]) {ans += C[26-(cur-'a')-1][len-i-1];cur++;} }printf("%lld\n",ans+1); }return 0 ;}