标签:
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