九度OJ 1491 求1和2的个数(组合数学)

题目链接

对数位DP,不太熟,组合的方法可能更好想,实现把所有的情况都考虑清楚。

例如算1的个数的时候。

假如第一位为n > 1,第一位可能为0-n-1,后面len-1位中1的和有(sum = (len-1)*10^(len-2))(枚举每一位是1,其他位置有10种可能);

这样还要注意第一位是1,这样有10^(len-1)个1;

第一位是n,继续递归下去。 

假如第一位为0,直接递归下去。

假如第一位为1情况,为sum + (后边数字+1(有0))+dfs(str+1);

二的情况与一类似,认真分析各种情况。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 #include <string>
 5 using namespace std;
 6 #define MOD 20123
 7 int o[201];
 8 int judge(char *str)
 9 {
10     int i,mod,len;
11     len = strlen(str);
12     mod = 0;
13     for(i = 0; i <= len-1; i ++)
14     {
15         mod = (mod*10 + str[i]-'0') % MOD;
16     }
17     return mod;
18 }
19 int dfs(char *str)
20 {
21     int len,sum;
22     len = strlen(str);
23     if(len == 1)
24     {
25         if(str[0] >= '1')
26             return 1;
27         else
28             return 0;
29     }
30     sum = (len-1)*o[len-2];
31     if(str[0] == '0')
32         return dfs(str+1)%MOD;
33     else if(str[0] == '1')
34         return (sum + judge(str+1)+1 + dfs(str+1))%MOD;
35     else if(str[0] > '1')
36         return ((str[0]-'0')*sum + o[len-1] + dfs(str+1))%MOD;
37     return 0;
38 }
39 int dfs2(char *str)
40 {
41     int len,sum;
42     len = strlen(str);
43     if(len == 1)
44     {
45         if(str[0] >= '2')
46             return 1;
47         else
48             return 0;
49     }
50     sum = (len-1)*o[len-2];
51     if(str[0] == '0')
52         return dfs2(str+1)%MOD;
53     else if(str[0] == '1')
54         return (sum + dfs2(str+1))%MOD;
55     else if(str[0] == '2')
56         return (2*sum + judge(str+1)+1 + dfs2(str+1))%MOD;
57     else if(str[0] > '2')
58         return ((str[0]-'0')*sum + o[len-1] + dfs2(str+1))%MOD;
59     return 0;
60 }
61 int main()
62 {
63     char str[201];
64     int i;
65     o[0] = 1;
66     for(i = 1; i <= 101; i ++)
67         o[i] = (10*o[i-1])%MOD;
68     while(scanf("%s",str)!=EOF)
69     printf("%d\n",(dfs(str)+dfs2(str))%MOD);
70     return 0;
71 }

 

 

posted @ 2013-03-12 13:26  Naix_x  阅读(816)  评论(0编辑  收藏  举报