poj1850 Code

Code
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 9282 Accepted: 4432

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

一种类型的题多做几道,就可以自己想啦~这次一点也没有依靠别人呐~

这个题就是告诉你有一种单词编码,就是把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;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值