版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wust_zzwh/article/details/47679791
Time Limit: 1000MS | Memory Limit: 30000KB | 64bit IO Format: %I64d & %I64u |
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.
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.
• 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
扫描二维码关注公众号,回复:
3353615 查看本文章
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;
}