Bomb(数位Dp)

布满荆棘的人生 2022-08-03 00:09 322阅读 0赞

Bomb

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)
Total Submission(s): 10373 Accepted Submission(s): 3657

Problem Description

The counter-terrorists found a time bomb in the dust. But this time the terrorists improve on the time bomb. The number sequence of the time bomb counts from 1 to N. If the current number sequence includes the sub-sequence “49”, the power of the blast would add one point.
Now the counter-terrorist knows the number N. They want to know the final points of the power. Can you help them?

Input

The first line of input consists of an integer T (1 <= T <= 10000), indicating the number of test cases. For each test case, there will be an integer N (1 <= N <= 2^63-1) as the description.

The input terminates by end of file marker.

Output

For each test case, output an integer indicating the final points of the power.

Sample Input

  1. 3
  2. 1
  3. 50
  4. 500

Sample Output

  1. 0
  2. 1
  3. 15
  4. Hint From 1 to 500, the numbers that include the sub-sequence "49" are "49","149","249","349","449","490","491","492","493","494","495","496","497","498","499", so the answer is 15.

Author

fatboy_cw@WHU

  1. #include<cstdio>
  2. #include<iostream>
  3. #include<cstring>
  4. #define ll long long
  5. using namespace std;
  6. ll dp[21][3];
  7. void init()
  8. {
  9. int i;
  10. memset(dp,0,sizeof(dp));
  11. dp[0][0]=1;
  12. /*
  13. dp[i][0]代表长度为 i 并且不含有49的数字的个数;
  14.   dp[i][1]代表长度为 i 并且不含有49,但是最高位是9的数字的个数;
  15.   dp[i][2]代表长度为 i 并且含有49的数字的个数。
  16. */
  17. for(i=1;i<21;i++)
  18. {
  19. dp[i][0]=dp[i-1][0]*10-dp[i-1][1];// 表示长度为 i 的不含有49的数字的个数等于
  20. // 长度为 i - 1 的不含有49的数字的个数*当前的数字
  21. dp[i][1]=dp[i-1][0];//表示长度为 i 的并且不含有49同时最高位是9的数字的个数等于,
  22. //长度为 i - 1 的不含有49的数字的个数,
  23. //因为只要在它的高一位加上一个9就可以了。
  24. dp[i][2]=dp[i-1][2]*10+dp[i-1][1];
  25. /*
  26. 表示长度为 i 的含有49的数字的个数等于,
  27. 长度为 i - 1 的数字的个数*当前的数字
  28. ,再加上长度为 i - 1 的
  29. 并且不含有49同时最高位是9的数字的个数,因为这个时候,
  30. 只要在高一位加上一个4就可以了,
  31. 这样在最高的两位就组成了一个49。*/
  32. }
  33. }
  34. int main()
  35. {
  36. int i,t,len,last,flag,a[22];
  37. ll ans,n;
  38. init();
  39. cin>>t;
  40. while(t--)
  41. {
  42. memset(a,0,sizeof(a));
  43. last=flag=ans=0;//flag用于判断这个数之前的数是否是49
  44. cin>>n;
  45. n++;
  46. len=1;
  47. while(n)
  48. {
  49. a[len++]=n%10;
  50. n/=10;
  51. }
  52. len--;
  53. for(i=len;i>=1;i--)
  54. {
  55. ans+=dp[i-1][2]*a[i];//在i之前的一位所有含有49数的种类*当前数
  56. if(flag)//如果这个数与前一个数组合成49
  57. {
  58. ans+=dp[i-1][0]*a[i];//这个数的种类就是下一位所有的非49数*当前数
  59. //比如4960,应该是6*1=6;
  60. }
  61. if(!flag&&a[i]>4)
  62. {
  63. ans+=dp[i-1][1];
  64. }
  65. if(last==4&&a[i]==9)
  66. {
  67. flag=true;
  68. }
  69. last=a[i];
  70. }
  71. printf("%I64d\n",ans);
  72. }
  73. }

因为后面的for循环求的是(0,n)的开区间的符合条件的数字的数目,题目要求[1,n]这个区间内的符合条件的数字的数目,所以要把区间的右端点加1。这样的处理方式比较方便,就不用判断这个端点是不是如何条件的数字了。

发表评论

表情:
评论列表 (有 0 条评论,322人围观)

还没有评论,来说两句吧...

相关阅读

    相关 数位DP 详解

    序 > 天堂在左,战士向右 引言 数位DP在竞赛中的出现几率极低,但是如果不会数位DP,一旦考到就只能暴力骗分。 以下是数位DP详解,涉及到的例题有:

    相关 数位dp小结

    数位dp小结 关于limit的问题 在数位dp中,limit的作用主要有两个。 控制枚举的界限,倘若没有界限,每一位的枚举范围都是0-9. 但如果有界限,

    相关 数位DP

    Problem Description 据说,QAQ 的幸运数字是含有 "47" (4 和 7 相邻)的数,例如 47, 147, 247, 470, 471, 2047