九度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 }