码迷,mamicode.com
首页 > 其他好文 > 详细

POJ1850 组合数学

时间:2014-08-08 17:57:46      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   strong   for   

POJ1850

问题重述:

用26个小写字母进行编码,编码规则如下:

1)每个编码中前一个字母必须小于后一个字母

2)编码按照长度从小到大排列,相同长度按字典序进行排列

输入一个字母串,求解该编码对应的数值。

问题分析:

该问题等价于求解小于输入编码的编码的数目。

对于编码X = x1,x2,x3,...xk, 小于X的编码可以分为两个部分

1)位数小于k的编码。

  这部分编码的数目 = C[26][1] + C[26][1] + ... + C[26][k - 1]

2)长度为k,且小于X的编码。

  假设Y为满足该条件的编码,现只需确定Y的数目。从左到右遍历编码X: i = 1 to k,假设X和Y的前i - 1位均相等且 yi != xi,那么 yi 必须满足 xi-1 = yi - 1 < yi < xi。

  对于yi的每一种取值, yi, yi + 1, ... yk只需满足递增关系即可, 共有C[26][25 - (yi - ‘a‘)]种编码。

根据以上分析,即可求出结果。

AC代码:

 1 //Memory: 204K        Time: 0MS
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 
 8 using namespace std;
 9 
10 string s, ss;
11 int c[27][27];
12 
13 void init()
14 {
15     for (int i = 0; i <= 26; i++) 
16         c[i][0] = c[i][i] = 1;
17 
18     for (int i = 1; i <= 26; i++)
19         for (int j = 0; j < i; j++)
20             c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
21 }
22 
23 int main()
24 {
25     cin >> s;
26         
27     int len = s.size();
28     for (int i = 0; i < len - 1; i++) {
29         if (s[i] > s[i + 1] || s[i] == s[i + 1]){
30             cout << 0 << endl;
31             return 0;
32         }
33     }
34 
35     init();
36     int ans = 0;
37     for (int i = 1; i <= len - 1; i++) {
38         ans += c[26][i];
39     }
40 
41     for (int i = 0; i < s[0] - a; i++) {
42         ans += c[25 - i][len - 1];
43     }
44 
45     for (int i = 1; i < len; i++) {
46         for (int j = s[i - 1] - a + 1; j < s[i] - a; j++)
47             ans += c[25 - j][len -1 - i];
48     }
49     cout << ans + 1 << endl;
50     
51     return 0;
52 }

 

POJ1850 组合数学,布布扣,bubuko.com

POJ1850 组合数学

标签:style   blog   http   color   os   io   strong   for   

原文地址:http://www.cnblogs.com/junxie/p/3899676.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!