您的位置:首页 > 其它

POJ 1850 组合编号

2017-07-28 17:10 225 查看
problem

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


思路

我的思路主要分两步:

1.先处理位数,相同位数的再到第二步处理。当位数不同时,可以用组合数直接算出前面单词的数量。比如当一个单词是5个字母时,前面长度不同的单词有长度1~4的,它们的数量即为C(26,1)+C(26,2)+C(26,3)+C(26,4)。

2.第二步处理相同位数前面有多少单词。还是基本组合问题(因为升序,相当于固定位置),主要利用后一个字母与前一个字母的差值字母在26个字母中的位置(因为升序)来分别决定需要循环的次数和组合数C(m,n)中的m,而n是由单词的长度决定的。

另外需要注意的是最后结果要+1才为ans,因为计算的是该单词前面的数量。以及在计算组合数时,是采用二维数组C[][]先存储的,以避免大量不必要的递归操作。

代码示例

//#define LOCAL
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=60;
/*
long long comb(int m,int n)
{
if(n==0) return 1;
if(n==1) return m;
if(n>m/2) return comb(m,m-n);
return (comb(m-1,n-1)+comb(m-1,n));
}
*/
LL C[maxn][maxn];
void getC()
{
for(int i=0;i<maxn;++i){
C[i][0]=C[i][i]=1;
for(int j=1;j<i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1];
}
}

char str[11];

int main()
{
#ifdef LOCAL
freopen("read.txt","r",stdin);
#endif // LOCAL
int len;
int flag;
long long ans;
getC();
while(cin>>str)
{
flag=0;
ans=0;
len=strlen(str);
//cout<<len<<endl;
//cout<<str[0]<<endl;
//cout<<C[10][5]<<endl;
for(int i=1;i<len;++i){
if(str[i-1]>=str[i]){
cout<<0<<endl;
flag=1;
break;
}
}

if(flag==1){
//cout<<0<<endl;
continue;
}

for(int i=1;i<=len-1;++i){
ans+=C[26][i];
}

for(int i=0;i<len;++i){
if(i==0){
for(int j=1;j<=str[i]-'a';++j) ans+=C[26-j][len-1-i];
continue;
}
for(int j=str[i-1]+1;j<str[i];++j) ans+=C[26-j+'a'-1][len-1-i];
}
cout<<++ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: