首页 > 代码库 > TOJ 1183 The Counting Problem 数位dp

TOJ 1183 The Counting Problem 数位dp

http://acm.tju.edu.cn/toj/showp1183.html

题意:从a写到b,问每个数字各写了几次。

分析:昨天做了一道how many 0‘s,这题算是拓展。考虑从0..a。1到9是一样的,如果目前考虑的是digit,枚举每位,左边填0..x-1,则右边随便填(10^右边长度),左边填x,如果a的当前位大于digit,那么右边还是随便填,如果等于,只能填0..右边最大值,如果大于则没有。而0不一样在于不能作为一个数的第一位,所以左边只能填1..x-1,还有如果目前枚举的是最高位则不能填0。

 

 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5  6 #define debug 0 7 int beg, end; 8 int d[20]; 9 int ans1[15], ans2[15];10 void cal(int x, int ans[])11 {12     for (int i = 0; i < 10; i++) ans[i] = 0;13     if (x == -1) return;14     if (x == 0){15         ans[0] = 1;16         return;17     }18     int len = 0;19     int xx = x;20     while(x){21         d[len++] = x % 10;22         x /= 10;23     }24     x = xx;25     for (int digit = 1; digit <= 9; digit ++){26         int sum = 0, res = x/10, cnt = 0, exp = 1;  //res为当前位的左边,cnt为右边,exp为右边随便填的总数27         for (int i = 0; i < len; i++){28             sum = sum + res * exp;           //左边填0..res-1,右边随便填29             if (digit < d[i]) sum = sum + exp;    //如果小于,左边填res,右边随便填30             else if (digit == d[i]) sum = sum + cnt+1;  //相等,即左边到当前位都是在最高的情况,右边只能填0..cnt31 32             if (debug){33                 if (digit == 4) printf("%d\n",sum);34             }35             cnt = cnt + d[i] * exp;36             exp *= 10;37             res /= 10;38         }39         ans[digit] = sum;40     }41     int sum = 1, res = x/10, cnt = 0, exp = 1;42     for (int i = 0; i < len; i++){43         if (res > 0) sum = sum + (res-1) * exp;    //单独算为0的情况,一个是左边从1开始,还有一个是最高位不能填044         if (d[i]) {45             if (i != len-1) sum = sum + exp;46         }47         else sum = sum + cnt + 1;48         cnt = cnt + d[i] * exp;49         exp *= 10;50         res /= 10;51     }52     ans[0] = sum;53 }54 int main()55 {56     while(scanf("%d %d", &beg, &end))57     {58         if (beg == 0 && end == 0) break;59         if (beg > end) swap(beg, end);60         cal(beg-1, ans1);61         cal(end, ans2);62         if (debug) for (int i = 0; i < 10; i++) printf("%d %d\n", ans1[i], ans2[i]);63         for (int i = 0; i < 10; i++) printf("%d%c", ans2[i]-ans1[i], i==9? \n:  );64     }65     return 0;66 }

 

TOJ 1183 The Counting Problem 数位dp