POJ 1850 Code

Time Limit: 1000MS Memory Limit: 30000KB 64bit IO Format: %I64d & %I64u

 Status

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
题意:给定字符串排序规则如下:

只有小写字母,先按照长度拍,长的序号大,在按照字母字典序拍,一个串中字母是升序(自然不能有相同的字母)

a  1

b  2

c  3

......

z  26

ab  27

ac 28

...

az  51

bc 52

.....

vwxyz - 83681 

现在输入字符串,求它的编号;

思路:

字符串的规律性很强,先考虑长度问题,加上长度已经固定为x,也就是说由x个字母组成的字符串(满足题目升序要求)有多少种,有26个字母选x个组成一个字符串,

种数就是组合数C(26,x),选出x个字符后排序只有一种(因为选出x个字母肯定没有重复的,既然是不同的x个字母的排列,而且必须升序,不就只有一种排列么-_-:);

那么就是C(26,x)种;对于输入的字符串计算长度为len,那么比len小的字符串比如排在它前面(题目说先按长度排序的),加到答案里既C(26,1)+C(26,2)+.....+C(26,len-1);

然后长度为len比输入字符串小的串的有多少个呢,数位dp咯,每个字母都有数字标号嘛,a对应0,z 对应25,字母位抽象成数字位(只不过数字位可以大于9,+.........+)

然后状态要保存前一位数字,因为题目要求升序,每次枚举都从前一位+1开始;

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<set>
#include<vector>
#include<map>
#include<stack>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1e6+5;
const int INF=0x3f3f3f3f;
typedef __int64 ll;
ll dp[30][30],sum[30],c[30];
int a[30];
bool vis[30];
string s;
ll dfs(int pos,int n,int pre,int limit)//数位dp
{
//基本上是模板,pos保存当前第几位,pre保存上一位字母,然后记忆化搜索
    if(pos==n)
        return 1;
    if(limit==0 && dp[pos][pre]!=-1) return dp[pos][pre];
    int upper=limit?a[pos]:25;
    ll ans=0;
    for(int i=pre+1;i<=upper;i++)//合法的字符串是递增的
    {//所以i从pre+1,也就是比前一位大一的数开始枚举
        ans+=dfs(pos+1,n,i,limit && i==a[pos]);//最后一个参数的处理就是模板,貌似没见过别的写法的;
    }
    if(limit==0) dp[pos][pre]=ans;
    return ans;
}
void solve()
{
    int pos=0;
    for(int i=0;i<s.size();i++)
        a[pos++]=s[i]-'a';
    printf("%I64d\n",dfs(0,pos,-1,1)+sum[s.size()-1]);
}
void C()//递推组合数
{
    c[0]=1;
    int n=26;
    for(int i=1;i<=26;i++)
        c[i]=c[i-1]*(n-i+1)/i;
}
void init()
{
    sum[0]=0;
    C();
    for(int i=1;i<=11;i++)
    {
        sum[i]+=sum[i-1]+c[i];//组合数的和
    }
    memset(dp,-1,sizeof dp);//初始化放里面也是对的,数位dp的特别之处:每个数满不满足条件只与数本身有关,
    //只不过每组数据给的区间不一样使得区间外的数不被统计,
    //当然不同的题这里的处理是不一样的,数满不满足条件如果和输入有关那就只能放里面
}
int main()
{
    init();
    while(cin>>s)
    {
        int tag=0;
        for(int i=1;i<s.size();i++)
            if(s[i]<s[i-1]) tag=1;//输入的串要合法
        if(tag)
        {
            printf("0\n");
            continue;//break也行(。。。。);
        }
        solve();
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值