【数位DP+离散化】Beautiful numbers CodeForces - 55D

àì夳堔傛蜴生んèń 2022-06-08 11:20 286阅读 0赞

Think:
1知识点:数位DP(+记忆化搜索)+离散化
2题意:输入一个区间,询问在这个区间内有多少个beautiful number,a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits.
3题目分析:
(1):由美丽的数字的定义可知,美丽数字为其每一位的lcm的倍数(2):lcm(1,2,3,4,5,6,7,8,9) = 2520,9个数字任意组合的lcm可推知为lcm(1,2,3,4,5,6,7,8,9)的因子
(3):当我们想要知道一个很大的数是否为一个new_lcm的倍数时,不需要存储这个很大的数,可以转而存储(这个很大的数)%lcm(1,2,3,4,5,6,7,8,9)
(4):dp[数位][截止当前位的数对2520取模][截止当前位的数的lcm]
(5):对于截止当前位的数的lcm可以通过离散化存储,否则直接存储的话三维数组dp[19+][2520+][2520+]会MLE,9个数字任意组合的gcd的数量为48个,因此离散化之后存储dp数组为dp[19+][2520+][48+]减少了使用的内存
(6):参考博客博主分析:
这里写图片描述
参考博客地址——感谢博主

vjudge题目链接

以下为Accepted代码

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. typedef long long LL;
  6. const int mod = 2520;/*lcm(1, 2, 3, 4, 5, 6, 7, 8, 9) = 2520*/
  7. int tp, link[24], hash[2520+14];
  8. LL dp[24][2520+14][48+14];
  9. LL gcd(LL a, LL b);
  10. LL dfs(int pos, int num, int lcm, bool is_max);
  11. LL solve(LL x);/*[0, x]*/
  12. int main(){
  13. int T, cnt = 0;
  14. memset(hash, 0, sizeof(hash));
  15. for(int i = 1; i <= 2520; i++){
  16. if(2520%i == 0)
  17. hash[i] = cnt++;
  18. }
  19. ///printf("%d\n", cnt);/*cnt = 48*/
  20. memset(dp, -1, sizeof(dp));
  21. LL l, r;
  22. scanf("%d", &T);
  23. while(T--){
  24. scanf("%lld %lld", &l, &r);
  25. printf("%lld\n", solve(r)-solve(l-1));
  26. }
  27. return 0;
  28. }
  29. LL gcd(LL a, LL b){
  30. if(!b) return a;
  31. else return gcd(b, a%b);
  32. }
  33. LL solve(LL x){
  34. tp = 0;
  35. while(x){
  36. link[tp++] = x%10;
  37. x /= 10;
  38. }
  39. return dfs(tp-1, 0, 1, true);
  40. }
  41. LL dfs(int pos, int num, int lcm, bool is_max){
  42. if(pos == -1)
  43. return num%lcm == 0;
  44. if(!is_max && ~dp[pos][num][hash[lcm]])
  45. return dp[pos][num][hash[lcm]];
  46. int up_top = 9;
  47. if(is_max)
  48. up_top = link[pos];
  49. LL sum = 0;
  50. int new_num, new_lcm;
  51. for(int i = 0; i <= up_top; i++){
  52. i ? new_lcm = i/gcd(i, lcm)*lcm : new_lcm = lcm;
  53. new_num = (num*10+i)%mod;
  54. sum += dfs(pos-1, new_num, new_lcm, is_max && i == up_top);
  55. }
  56. if(!is_max)
  57. dp[pos][num][hash[lcm]] = sum;
  58. return sum;
  59. }

发表评论

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

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

相关阅读