标签:
| Time Limit: 1000MS | Memory Limit: 30000K | |
| Total Submissions: 8505 | Accepted: 4030 |
Description
Input
Output
Sample Input
bf
Sample Output
55
题意:
将字母a-z进行排列,然后再进行编号,符合以下三个规则:
1、在长度上是递增的;
2、长度一样的时候,按照字典序进行排列;
3、以a为开始编排,样例如下:
a - 1
b - 2
...
z - 26
ab - 27
...
az - 51
bc - 52
...
vwxyz - 83681
...
思路:因为是升序哒,所以但凡事输入的字符串存在降序的序列,就直接输出0,然后结束。
这道题大体来说分两部分来求解:
1、算出长度小于所给字符串的所有字符串的个数;
2、算出长度等于所给字符串但排在前面的所有字符串的个数。
对于长度小于所给字符串的情况,我们可以先分别求出个长度的个数,然后相加。通过推可以得出n字符串的长度的排列组合数是
对于小于当前长度的序列直接将从1-(len-1)字符串长度的序列全部相加,对于和当前len长度相同的,请看下面的例子:
假设所给字符串为vwxyz,长度为5,第一个字符为‘v‘,则我们可以假定第一个字符从‘a‘到‘z‘:
当假定字符串为‘a‘时,后面4个位置可以安排大于‘a‘的25个字符,所以有种选择方法;
当假定字符串为‘b‘时,后面4个位置可以安排大于‘b‘的24个字符,所以有种选择方法;
............
当假定字符串为‘u‘时,后面4个位置可以安排大于‘u‘的5个字符,所以有种选择方法;
然后对于后面的字符也是一样的进行求解,再将这些结果全部加起来就可
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <set>
#include <queue>
#include <stack>
#include <map>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const double pi= acos(-1.0);
int c[27][27]={0};
void C()//计算当前字符串长度下的符合规则的排列总数
{
int i,j;
for(i=0;i<27;i++){
c[i][0]=1;
c[i][i]=1;
}
//以下是排列组合的递推公式
for(i=1;i<27;i++)
for(j=1;j<27;j++)
c[i][j]=c[i-1][j-1]+c[i-1][j];
}
int main()
{
int i,j,k;
char str[15];
LL sum;
int cnt;
C();
while(~scanf("%s",str)){
int len=strlen(str);
sum=0;
for(i=0;i<len-1;i++)
if(str[i]>str[i+1]){
printf("0\n");
return 0;
}
for(i=1;i<len;i++)
sum+=c[26][i];//c[26][i]表示长度为i的字符串的排列个数
for(i=0;i<len;i++){
if(i==0)
cnt='a';
else
cnt=str[i-1]+1;//根据升序规则,当前位置的cnt至少要比str前一位置的字符大1,因为每一个的排列的开始为a,ab,abc,abcd
while(cnt<str[i]){//根据升序规则,当前位置的ch最多只能比str这个位置实际上的字符小1
sum+=c['z'-cnt][len-i-1];//小于等于ch的字符串的排列个数在上面已经计算,所以当前能够选择的字符总数为'z'-cnt
//cnt位置后面(不包括cnt)剩下的位数,就是从'z'-cnt选择len-1-i个字符
cnt++;
}
}
printf("%lld\n",sum+1);//sum算的是比当前str小的所有的组合数,并不包括其本身,所以在这加1.
}
return 0;
}
标签:
原文地址:http://blog.csdn.net/u013486414/article/details/44860765