题目大意:

求  1(m)到n直接有多少个数字x满足 x可以整出这个数字的每一位上的数字

思路:

整除每一位。只需要整除每一位的lcm即可

但是数字太大,dp状态怎么表示呢

发现 1~9的LCM 是2520 ....也就是说只要对这个数mod2520 剩下的余数能整除lcm就可以整除了。。

计数的时候还有一个技巧,具体见注释

此外这个题还卡常数了,预处理lcm才过了。。

代码如下:

  1. #include <iostream>
  2. #include <stdio.h>
  3. #include<string.h>
  4. #include<algorithm>
  5. #include<string>
  6. #include<ctype.h>
  7. using namespace std;
  8. #define LCM 2520
  9. long long dp[][LCM+][][];
  10. long long n;
  11. int m;
  12. int state[],hs[],s;
  13. bool vi[];
  14. int d[];
  15. int Lcm[][];
  16. int gcd(int a,int b)
  17. {
  18. return b?gcd(b,a%b):a;
  19. }
  20. int lcm(int a,int b)
  21. {
  22. if(b==)
  23. return a;
  24. return a/gcd(a,b)*b;
  25. }
  26.  
  27. void ini()
  28. {
  29. m=;
  30. while(n)
  31. {
  32. d[++m]=n%;
  33. n/=;
  34. }
  35. reverse(d+,d+m+);
  36. }
  37. void DP()
  38. {
  39. memset(dp,,sizeof(dp));
  40. //先放最高位
  41. for(int i=;i<d[];i++)
  42. {
  43. dp[][i][hs[i]][]=; //dp...[0]存储的是前i位的数小于所求数的方案
  44. }
  45. dp[][d[]][hs[d[]]][]=; //dp...[1]存储的是前i位的数等于所求数的方案
  46. //从高位往下转移
  47. for(int i=;i<=m;++i)
  48. {
  49. for(int j=;j<;++j)
  50. dp[i][j][hs[j]][]=; //从大于1的数位开始放1~9都肯定小于所求数
  51. for(int j=;j<;++j)
  52. {
  53. for(int k=;k<s;++k)
  54. {
  55. if(dp[i-][j][k][]==&&dp[i-][j][k][]==)
  56. continue;
  57. for(int t=;t<=;++t)
  58. {
  59. int sum=(j*+t)%LCM;
  60. int L=Lcm[k][t];
  61. dp[i][sum][hs[L]][]+=dp[i-][j][k][];
  62.  
  63. //在当前位放的数小于等于所求数的当前为数的情况可以继承高位都等于所求数的方案
  64. //否则,只能继承高位小于所求数的方案
  65. if(t<d[i]) //当前位放的数小于所求数的当前位
  66. {
  67. dp[i][sum][hs[L]][]+=dp[i-][j][k][];
  68. }
  69. if(t==d[i]) //当前位放的数等于所求数的当前位
  70. {
  71. dp[i][sum][hs[L]][]+=dp[i-][j][k][];
  72. }
  73.  
  74. }
  75. }
  76. }
  77. }
  78. }
  79. void setstate()
  80. {
  81. memset(vi,,sizeof(vi));
  82. s=;
  83. int tmp;
  84. for(int i=;i<(<<);i++)
  85. {
  86. tmp=;
  87. for(int j=;j<;j++)
  88. {
  89. if((<<j)&i)
  90. {
  91. tmp=lcm(j+,tmp);
  92. }
  93. }
  94. if(vi[tmp]==)
  95. {
  96. state[s]=tmp;
  97. hs[tmp]=s++;
  98. vi[tmp]=;
  99. }
  100. }
  101. for(int i=;i<s;i++)
  102. {
  103. for(int j=;j<=;j++)
  104. Lcm[i][j]=lcm(state[i],j);
  105. }
  106. }
  107. long long cal()
  108. {
  109. long long ans=;
  110.  
  111. for(int i=;i<;i++)
  112. {
  113. for(int j=;j<s;j++)
  114. {
  115. if(i%state[j]==)
  116. ans+=dp[m][i][j][]+dp[m][i][j][];
  117. }
  118. }
  119. return ans;
  120. }
  121. long long solve(long long x)
  122. {
  123. n=x;
  124. ini();
  125. DP();
  126. return cal();
  127. }
  128. int main()
  129. {
  130. long long a,b;
  131. setstate();
  132. int t;
  133. scanf("%d",&t);
  134. while(t--)
  135. {
  136. //scanf("%I64d%I64d",&a,&b);
  137. scanf("%I64d",&a);
  138. //cout<<solve(b)-solve(a-1)<<endl;
  139. cout<<solve(a)<<endl;
  140. }
  141. return ;
  142. }

FZU2179/Codeforces 55D beautiful number 数位DP的更多相关文章

  1. codeforces 55D - Beautiful numbers(数位DP+离散化)

    D. Beautiful numbers time limit per test 4 seconds memory limit per test 256 megabytes input standar ...

  2. CodeForces - 55D - Beautiful numbers(数位DP,离散化)

    链接: https://vjudge.net/problem/CodeForces-55D 题意: Volodya is an odd boy and his taste is strange as ...

  3. Codeforces - 55D Beautiful numbers (数位dp+数论)

    题意:求[L,R](1<=L<=R<=9e18)区间中所有能被自己数位上的非零数整除的数的个数 分析:丛数据量可以分析出是用数位dp求解,区间个数可以转化为sum(R)-sum(L- ...

  4. CodeForces - 55D Beautiful numbers —— 数位DP

    题目链接:https://vjudge.net/problem/CodeForces-55D D. Beautiful numbers time limit per test 4 seconds me ...

  5. codeforces 55D. Beautiful numbers 数位dp

    题目链接 一个数, 他的所有位上的数都可以被这个数整除, 求出范围内满足条件的数的个数. dp[i][j][k], i表示第i位, j表示前几位的lcm是几, k表示这个数mod2520, 2520是 ...

  6. Codeforces 55D Beautiful Number

    Codeforces 55D Beautiful Number a positive integer number is beautiful if and only if it is divisibl ...

  7. beautiful number 数位DP codeforces 55D

    题目链接: http://codeforces.com/problemset/problem/55/D 数位DP 题目描述: 一个数能被它每位上的数字整除(0除外),那么它就是beautiful nu ...

  8. Codeforces 55D Beautiful Number (数位统计)

    把数位dp写成记忆化搜索的形式,方法很赞,代码量少了很多. 下面为转载内容:  a positive integer number is beautiful if and only if it is  ...

  9. HDU 5179 beautiful number 数位dp

    题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=5179 bc(中文): http://bestcoder.hdu.edu.cn/contes ...

随机推荐

  1. crtmpserver 基本流程分析

    近期在研究crtmpserver,这里记录下学习过程,首先我们先分析下基本流程. 1.初始化流程 InitNetworking---初始化网络 Initialize Logger::Init()--- ...

  2. Android 自定义View (一)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24252901 很多的Android入门程序猿来说对于Android自定义View ...

  3. mdf导入sqlServer

    导入mdf有两种方法:   (需要mdf和ldf两个文件) 1.   在SQL企业管理器中,选择左边树型列表,根节点即"数据库"的文件夹图标,右键"所有任务"→ ...

  4. 系统管理中 bash shell 脚本常用方法总结

    在日常系统管理工作中,需要编写脚本来完成特定的功能,编写shell脚本是一个基本功了!在编写的过程中,掌握一些常用的技巧和语法就可以完成大部分功能了,也就是2/8原则 1. 单引号和双引号的区别 单引 ...

  5. iOS9之后对于NSURL的编码转换方法变化说明

    在iOS9之后,官方推荐使用下面的方法对NSString进行转换 - (nullable NSString *)stringByAddingPercentEncodingWithAllowedChar ...

  6. 【转】深入理解Java内存模型(六)——final

    与前面介绍的锁和volatile相比较,对final域的读和写更像是普通的变量访问.对于final域,编译器和处理器要遵守两个重排序规则: 在构造函数内对一个final域的写入,与随后把这个被构造对象 ...

  7. PHP preg_match正则表达

    在php中preg_match()函数是用来执行正则表达式的一个常用的函数,下面我来给大家详细介绍preg_match使用方法. 函数用法 int preg_match_all ( string pa ...

  8. 武汉科技大学ACM :1006: 华科版C语言程序设计教程(第二版)习题7.15

    Problem Description 输入n个字符串(n<=100),输出其中最长的串,如果有多个则取最先找到的那一个. Input 多组测试数据. 每组测试数据第一行包含一个整数n,表示一共 ...

  9. rtmpdump代码分析 转

    RTMPdump 源代码分析 1: main()函数 rtmpdump 是一个用来处理 RTMP 流媒体的工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, ...

  10. 使用 HTTP 缓存机制提升系统性能

    摘要 HTTP缓存机制定义在HTTP协议标准中,被现代浏览器广泛支持,同时也是一个用于提升基于Web的系统性能的广泛使用的工具.本文讨论如何使用HTTP缓存机制提升基于Web的系统,以及如何避免误用. ...