POJ 3286 How many 0's?(数位DP)
终于过了,边界让我wa了好几次,猥琐的用AC代码对拍,很无奈,用非常麻烦的方法。写一下,估计以后再碰到,肯定看不懂这是写的什么了。
以前做过,统计1和2的,统计0比1和2麻烦多了,有前导0的情况,不太好弄。
算是用统计方法,先把sp[len-1]所有的加上,长度为len-1的情况。
然后就是长度为len的情况。从高位到低位,遍历。
如果此位是0,judge(str+1) + 1 + dfs(str+1),是统计当前为是0的,多少情况,但是会漏解,算是受以前那个题统计1和2的影响把。
如果下一位是0,那么就不用管了,交给下位统计去把。下位不是0,计算会漏掉下位是0的情况,所以定住下位是0,组合一下长度len-2的所有0的个数。
不是0的情况,类似。
以前那个题的题解http://www.cnblogs.com/naix-x/archive/2013/03/12/2955544.html
完全没有策略,乱写,乱搞过的。。。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <string> 5 using namespace std; 6 #define LL __int64 7 LL dp[201],sp[201],o[201]; 8 LL judge(char *str) 9 { 10 int i,len; 11 LL ans; 12 len = strlen(str); 13 ans = 0; 14 for(i = 0; i <= len-1; i ++) 15 { 16 ans = (ans*10 + str[i]-'0'); 17 } 18 return ans; 19 } 20 LL dfs(char *str) 21 { 22 int len; 23 LL sum; 24 len = strlen(str); 25 if(len == 1) 26 return 1; 27 sum = (len-1)*o[len-2]; 28 if(str[0] == '0') 29 { 30 if(str[1] == '0') 31 return judge(str+1) + 1 + dfs(str+1); 32 else if(len >= 3) 33 return judge(str+1) + 1 +dfs(str+1)+o[len-2] + (len-2)*o[len-3]; 34 else 35 return judge(str+1) + 1 + dfs(str+1); 36 } 37 else 38 { 39 if(str[1] == '0') 40 return (str[0]-'1')*sum + dfs(str+1); 41 else if(len >= 3) 42 return (str[0]-'1')*sum + dfs(str+1)+o[len-2] + (len-2)*o[len-3]; 43 else 44 return (str[0]-'1')*sum + dfs(str+1); 45 } 46 } 47 LL fun(LL x) 48 { 49 int i,len; 50 char str[201]; 51 if(x == 0) return 1; 52 else if(x < 0) return 0; 53 len = 0; 54 while(x) 55 { 56 str[len++] = x%10+'0'; 57 x = x/10; 58 } 59 for(i = 0; i < len/2; i ++) 60 { 61 swap(str[i],str[len-i-1]); 62 } 63 str[len] = '\0'; 64 return sp[len-1] + dfs(str); 65 } 66 int main() 67 { 68 int i; 69 LL temp = 1,x,y; 70 dp[1] = 1; 71 sp[1] = 1; 72 o[1] = 10; 73 o[0] = 1; 74 for(i = 2; i <= 15; i ++) 75 { 76 dp[i] = (i-1)*9*temp; 77 sp[i] = sp[i-1] + dp[i]; 78 o[i] = 10*o[i-1]; 79 temp = temp*10; 80 } 81 while ( scanf("%I64d%I64d",&x,&y) && (y>=0) ) 82 { 83 printf("%I64d\n",fun(y)-fun(x-1)); 84 } 85 return 0; 86 }