POJ 1850 Code(组合数学)

Description

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),问能经过多少步达到,从a开始逐渐演变。

思路:较难的组合数学,利用杨辉三角打个表,作为组合数的计算。分析如何变成当前的串可以大体分为2步,1)当位数小于当前串的位数;2)位数和当前串相同。

1)位数比当前的串小的时侯,直接ans+=c[26][i].

2)当位数相同的时候,


拿s=bdg这个字符串做例子。首先,s的长度len=3

已经是3位的,因为所谓的code是从a增到z再增到ab再增到yz再增到bdg的,即先从1位增到2位再增到3位的。

那么a增到z,code量是26个字母里面选1个,ab增到yz,code量是26个字母里选两个。

然后要计算yz到bdg的过程中有多少code量。

bdg的前面是经过a_ _的。那么a开头的3位有多少个呢?就是25个字母里选2个。因为空格里的字母不能小于等于a。,所以不会包含a。

然后看第2位,是一个d,d和b之间有个c,那么还需要计算c_有多少个,是23个里面选1个

然后看g,g和d之间有e和f。故就是1+1.

所以答案等于C[26][1]+C[26][2]+C[25][2] +C[23][1]+1+1

(摘自:http://m.blog.csdn.net/blog/a799581229/38146971)

//多组数据形式会WA,尽量做题的时候让用什么就用什么,不要乱创。。。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define LL long long
#define inf 0x3f3f3f3f
using namespace std;
char a[1000];
int c[30][30];
void ini()
{
    for(int i=0;i<27;i++)//虽然从零开始但是以后的计算都是1开始
        for(int j=0;j<=i;j++)
            if(j==0||i==j)
                c[i][j]=1;
            else
                c[i][j]=c[i-1][j-1]+c[i-1][j];
}
int main()
{
    int n,m,x,k,i,j;
    memset(c,0,sizeof(c));
    ini();
    gets(a+1);

        int ans=0;
        int l=strlen(a+1);
        bool vis=false;
        for(i=1;i<=l-1;i++)
            if(a[i]>a[i+1])
            {
                printf("0\n");
                return 0;
            }
        for(i=1;i<=l-1;i++)
        {
            ans+=c[26][i];
        }
        a[0]='a'-1;//为了使刚开始的部分不跃界
        for(i=1;i<=l;i++)
        {
            for(j=a[i-1]-'a'+1;j<a[i]-'a';j++)
            {//计算相邻两字母的间隔
                ans+=c[25-j][l-i];
            }
        }
        printf("%d\n",ans+1);
    return 0;
}



你可能感兴趣的:(组合数学)