题意:
给定区间[a,b],求将区间中所有数写在黑板上,要写的数字‘1’的次数。(1 <= a,b <= 10^8)
解法:
将题转化成f(b+1) - f(a)的形式。普通的数位DP。
tag:数位DP

1 /* 2 * Author: Plumrain 3 * Created Time: 2013-12-15 23:53 4 * fILE nAME: dp-fzU-2113.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <cstring> 9 10 using namespace std; 11 12 #define CLR(x) memset(x, 0, sizeof(x)) 13 typedef long long int64; 14 int64 d[25][20]; 15 int dit[25]; 16 17 int64 mypow(int64 p, int64 n) 18 { 19 int64 ret = 1; 20 while (n){ 21 if (n & 1) ret *= p; 22 n >>= 1; 23 p *= p; 24 } 25 return ret; 26 } 27 28 void d_init() 29 { 30 CLR (d); 31 d[1][1] = 1; 32 for (int i = 2; i < 25; ++ i){ 33 d[i][1] = mypow(10, i-1); 34 for (int j = 0; j < 10; ++ j) 35 for (int k = 0; k < 10; ++ k) 36 d[i][j] += d[i-1][k]; 37 } 38 } 39 40 int64 gao(int64 x) 41 { 42 int len = 0; 43 while (x){ 44 dit[len++] = x % 10; 45 x /= 10; 46 } 47 dit[len] = 0; 48 49 int64 ret = 0; 50 int flag = 0; 51 for (int i = len-1; i >= 0; -- i){ 52 ret += dit[i] * mypow(10, i) * flag; 53 for (int j = 0; j < dit[i]; ++ j) 54 ret += d[i+1][j]; 55 if (dit[i] == 1) ++ flag; 56 } 57 return ret; 58 } 59 60 int main() 61 { 62 d_init(); 63 int64 a, b; 64 while (cin >> a >> b) 65 cout << gao(b+1) - gao(a) << endl; 66 return 0; 67 }