hdu 2089 不要62 hdu 3555 Bomb (数位DP)
hdu 2089 不要62
题意:给出两个数,求区间内不带4和62的数的个数。(PS:62是连续的两位)
思路:
dp[i][0]表示前i位不含不吉利数的个数(如i=4,则范围为0~9999,下同)
dp[i][1]表示前i位不含不吉利数且首位是2的数的个数
dp[i][2]表示前i位含不吉利数的数的个数。
则有
dp[i][0] = dp[i-1][0] * 9 - dp[i-1][1]
dp[i][1] = dp[i-1][0]
dp[i][2] = dp[i-1][2] * 10 + dp[i-1][0] + dp[i-1][1]
预处理得到dp数组
然后从高往低逐位求答案。
例子,如数5678
按
0~4999
5000~5599
5600~5669
5670~5678
的顺序求解。
最低位处处理要特别留意。
参考:http://blog.csdn.net/acm_cxlove/article/details/7819907
1 #include <cstdio>
2 #include <cstring>
3
4 int dp[10][3], bit[10];
5
6 void init()
7 {
8
9 dp[1][0] = 9; dp[1][1] = 1; dp[1][2] = 1;
10 for(int i=2; i<=6; i++)
11 {
12 dp[i][0] = dp[i-1][0] * 9 - dp[i-1][1];
13 dp[i][1] = dp[i-1][0];
14 dp[i][2] = dp[i-1][0] + dp[i-1][1] + dp[i-1][2] * 10;
15 }
16 }
17
18 int solve(int n)
19 {
20 memset(bit, 0, sizeof(bit));
21 int len = 0;
22 while(n>0)
23 {
24 bit[++len] = n%10;
25 n /= 10;
26 }
27 bit[len+1] = 0;
28 int ret = 0, flag = 0;
29 for(int i=len; i>=2; i--)
30 {
31 ret += dp[i-1][2] * bit[i];
32 if(flag==1)
33 ret += dp[i-1][0] * bit[i];
34 if(flag==0 && bit[i]>4)
35 ret += dp[i-1][0];
36 if(flag==0 && bit[i+1]==6 && bit[i]>2)
37 ret += dp[i][1];
38 if(flag==0 && bit[i]>6)
39 ret += dp[i-1][1];
40 if(bit[i]==4 || bit[i]==2 && bit[i+1]==6)
41 flag = 1;
42 }
43 if(flag==1) ret += bit[1] + 1;
44 if(flag==0 && bit[1]>=4) ret++;
45 if(flag==0 && bit[1]>=2 && bit[2]==6) ret++;
46 return ret;
47 }
48
49 int main()
50 {
51 int l, r;
52 init();
53 /*
54 for(int i=1; i<=6; i++)
55 {
56 for(int j=0; j<=2; j++)
57 printf("%d ",dp[i][j]);
58 printf("\n");
59 }
60 */
61 while(scanf("%d%d",&l,&r)!=EOF)
62 {
63 if(l==0 && r==0) break;
64
65 if(l>r)
66 {
67 int temp;
68 temp = l; l = r; r = temp;
69 }
70 int ans = solve(r) - solve(l-1);
71 //printf("%d %d %d\n",solve(l),solve(r),ans);
72 printf("%d\n",r-l+1-ans);
73 }
74 return 0;
75 }
2 #include <cstring>
3
4 int dp[10][3], bit[10];
5
6 void init()
7 {
8
9 dp[1][0] = 9; dp[1][1] = 1; dp[1][2] = 1;
10 for(int i=2; i<=6; i++)
11 {
12 dp[i][0] = dp[i-1][0] * 9 - dp[i-1][1];
13 dp[i][1] = dp[i-1][0];
14 dp[i][2] = dp[i-1][0] + dp[i-1][1] + dp[i-1][2] * 10;
15 }
16 }
17
18 int solve(int n)
19 {
20 memset(bit, 0, sizeof(bit));
21 int len = 0;
22 while(n>0)
23 {
24 bit[++len] = n%10;
25 n /= 10;
26 }
27 bit[len+1] = 0;
28 int ret = 0, flag = 0;
29 for(int i=len; i>=2; i--)
30 {
31 ret += dp[i-1][2] * bit[i];
32 if(flag==1)
33 ret += dp[i-1][0] * bit[i];
34 if(flag==0 && bit[i]>4)
35 ret += dp[i-1][0];
36 if(flag==0 && bit[i+1]==6 && bit[i]>2)
37 ret += dp[i][1];
38 if(flag==0 && bit[i]>6)
39 ret += dp[i-1][1];
40 if(bit[i]==4 || bit[i]==2 && bit[i+1]==6)
41 flag = 1;
42 }
43 if(flag==1) ret += bit[1] + 1;
44 if(flag==0 && bit[1]>=4) ret++;
45 if(flag==0 && bit[1]>=2 && bit[2]==6) ret++;
46 return ret;
47 }
48
49 int main()
50 {
51 int l, r;
52 init();
53 /*
54 for(int i=1; i<=6; i++)
55 {
56 for(int j=0; j<=2; j++)
57 printf("%d ",dp[i][j]);
58 printf("\n");
59 }
60 */
61 while(scanf("%d%d",&l,&r)!=EOF)
62 {
63 if(l==0 && r==0) break;
64
65 if(l>r)
66 {
67 int temp;
68 temp = l; l = r; r = temp;
69 }
70 int ans = solve(r) - solve(l-1);
71 //printf("%d %d %d\n",solve(l),solve(r),ans);
72 printf("%d\n",r-l+1-ans);
73 }
74 return 0;
75 }
hdu3555
1 #include <cstdio>
2 #include <cstring>
3
4 __int64 dp[25][3];
5 int bit[25];
6
7 void init()
8 {
9 dp[1][0] = 10; dp[1][1] = 1; dp[1][2] = 0;
10 for(int i=2; i<=19; i++)
11 {
12 dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1]; //不含49数
13 dp[i][1] = dp[i-1][0]; //不含49首位为9的数
14 dp[i][2] = dp[i-1][1] + dp[i-1][2]*10; //含49数
15 }
16 }
17
18 __int64 solve(__int64 n)
19 {
20 int len = 0;
21 while(n>0)
22 {
23 bit[++len] = n%10;
24 n /= 10;
25 }
26 bit[len+1] = 0;
27
28 __int64 ret = 0;
29 int flag = 0;
30 for(int i=len; i>=2; i--)
31 {
32 ret += dp[i-1][2] * bit[i];
33 if(flag==1)
34 ret += dp[i-1][0] * bit[i];
35 if(flag==0 && bit[i]>4)
36 ret += dp[i-1][1];
37 if(bit[i+1]==4 && bit[i]==9)
38 flag = 1;
39 }
40 if(flag==1) ret += bit[1] + 1; //这两行调很久
41 if(flag==0 && bit[2]==4 && bit[1]==9) ret++;
42 return ret;
43 }
44
45 int main()
46 {
47 int t;
48 __int64 n;
49 init();
50 scanf("%d",&t);
51 while(t--)
52 {
53 scanf("%I64d",&n);
54 printf("%I64d\n",solve(n));
55 }
56 return 0;
57 }
2 #include <cstring>
3
4 __int64 dp[25][3];
5 int bit[25];
6
7 void init()
8 {
9 dp[1][0] = 10; dp[1][1] = 1; dp[1][2] = 0;
10 for(int i=2; i<=19; i++)
11 {
12 dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1]; //不含49数
13 dp[i][1] = dp[i-1][0]; //不含49首位为9的数
14 dp[i][2] = dp[i-1][1] + dp[i-1][2]*10; //含49数
15 }
16 }
17
18 __int64 solve(__int64 n)
19 {
20 int len = 0;
21 while(n>0)
22 {
23 bit[++len] = n%10;
24 n /= 10;
25 }
26 bit[len+1] = 0;
27
28 __int64 ret = 0;
29 int flag = 0;
30 for(int i=len; i>=2; i--)
31 {
32 ret += dp[i-1][2] * bit[i];
33 if(flag==1)
34 ret += dp[i-1][0] * bit[i];
35 if(flag==0 && bit[i]>4)
36 ret += dp[i-1][1];
37 if(bit[i+1]==4 && bit[i]==9)
38 flag = 1;
39 }
40 if(flag==1) ret += bit[1] + 1; //这两行调很久
41 if(flag==0 && bit[2]==4 && bit[1]==9) ret++;
42 return ret;
43 }
44
45 int main()
46 {
47 int t;
48 __int64 n;
49 init();
50 scanf("%d",&t);
51 while(t--)
52 {
53 scanf("%I64d",&n);
54 printf("%I64d\n",solve(n));
55 }
56 return 0;
57 }