题目来源:http://codeforces.com/problemset/problem/55/D

Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by each of its nonzero digits. We will not argue with this and just count the quantity of beautiful numbers in given ranges.

Input

The first line of the input contains the number of cases t (1 ≤ t ≤ 10). Each of the next t lines contains two natural numbers li and ri (1 ≤ li ≤ ri ≤ 9 ·1018).

Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cin (also you may use %I64d).

Output

Output should contain t numbers — answers to the queries, one number per line — quantities of beautiful numbers in given intervals (from li to ri, inclusively).

Input
1
1 9
Output
9
Input
1
12 15
Output
2

Beautiful numbers定义:能被自身所有非零数位整除的数。就比如15是Beautiful numbers,因为15可以被1,5整除,14不是,因为14不能被4整除。

问:n到m区间内有多少个Beautiful numbers

解题思路:一眼看很容易想到这是一道数位dp的题,我们可以想到:如果这个数是 Beautiful numbers,那么它一定可以被他的所有非零数位的最小公倍数整除。

1-9的最小公倍数是2520

我们可以定义某个状态dp[i][j][k]为第i号数位,j为当前表示的数字,k为当前数位的最小公倍数

如果直接这样写的话,j的范围就是1 ~ 9 ·1018,这肯定是不行的,这里有一个取模的规律:a%(b*c)%c=a%c

所以我们就可以把j的范围缩小到1-2520(1到9的最小公倍数)了。

然而这样还是不行,因为无法开出20*2520*2520的数组,我们可以知道1-9的组合的最小公倍数一定可以被2520整除的,所以先把先对1-2520进行离散化,离散化后可以发现其实只有48个有用的而已,那么就可以开20*2520*50的数组来

存状态了。

最小公倍数:    1  2  3  4  5  6  7  8  9  10  12  14  15  18  20  ...  1260  2520

hash1的值:1  2  3  4  5  6  7  8  9  10  11  12  13  14  15   ...  47  48

比如我们查找1-20的beautiful numbers 有以下过程(以下说明过程使用的数组以代码中为标准):

首先进入solve函数得到:a【0】=0,a【1】=2。接下来进入dfs函数:最先我们会得到dp【-1】【0】【1】=1,dp【-1】【1】【1】=1,dp【-1】【2】【2】=1,dp【-1】【3】【3】=1。。。dp【-1】【9】【9】=1(这里的-1只是模拟过程,并不代表实际情况)

的值,然后因为此时limit=false,所以dp【0】【0】【1】=sum{这些值的和}=10

同理可以得到10-19的beautiful number dp【-1】【10】【1】=1,dp【-1】【11】【1】=1,dp【-1】【12】【2】=1.。。dp【-1】【19】【9】=0;

此时limit=false ,dp【0】【1】【1】=4;

最后20也为beautiful number所以sum=15,但是我们在计算0-9的时候,误把0也记录了,所以最终答案为14.

这里插上本人的AC代码。。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<stack>
#include<cstdio>
#include<map>
#include<set>
#include<string>
#include<queue>
using namespace std;
#define inf 0x3f3f3f3f
typedef long long ll;
const int maxn=+;
ll dp[][maxn][];
int a[],hash1[maxn];
inline ll gcd(ll i,ll j){
return j==?i:gcd(j,i%j);
}
inline ll lcm(ll i,ll j){
return i/gcd(i,j)*j;
}
ll dfs(ll pos,ll sum,ll sum1,bool limit){
if(pos==-){
return sum%sum1==;
}
if(!limit&&dp[pos][sum][hash1[sum1]]!=-){
// cout<<pos<<endl;
// cout<<dp[pos][sum][hash1[sum1]]<<endl;
return dp[pos][sum][hash1[sum1]];
}
ll up=limit?a[pos]:;
ll ans=;
for(int i=;i<=up;i++){
ans+=dfs(pos-,(sum*+i)%,i==?sum1:lcm(sum1,i),(i==up)&&limit);
}
if(!limit)
dp[pos][sum][hash1[sum1]]=ans;
return ans;
}
ll solve(ll s){
memset(a,,sizeof(a));
int len=;
while(s){
a[len++]=s%;
s/=;
}
return dfs(len-,,,true);
}
int main(){
int t;
int cnt=;
ll l,r;
scanf("%d",&t);
for(int i=;i<=;i++)
{
if(%i==)
hash1[i]=cnt++;
}
memset(dp,-,sizeof(dp));
while(t--){
cin>>l>>r;
//cout<<solve(l-1)<<" "<<solve(r)<<endl;
cout<<solve(r)-solve(l-)<<endl;
//cin>>l;
// cout<<solve(l)<<endl;
}
return ;
}

CodeForces - 55D(数位dp,离散化)的更多相关文章

  1. Codeforces 55D (数位DP+离散化+数论)

    题目链接: http://poj.org/problem?id=2117 题目大意:统计一个范围内数的个数,要求该数能被各位上的数整除.范围2^64. 解题思路: 一开始SB地开了10维数组记录情况. ...

  2. codeforces 55D 数位dp

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

  3. CodeForces 55D "Beautiful numbers"(数位DP+离散化处理)

    传送门 参考资料: [1]:CodeForces 55D Beautiful numbers(数位dp&&离散化) 我的理解: 起初,我先定义一个三维数组 dp[ i ][ j ][ ...

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

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

  5. Codeforces 628D 数位dp

    题意:d magic number(0<=d<9)的意思就是一个数,从最高位开始奇数位不是d,偶数位是d 题目问,给a,b,m,d(a<=b,m<2000)问,a,b之间有多少 ...

  6. codeforces 401D (数位DP)

    思路:很明显的数位dp,设dp[i][j] 表示选取数字的状态为i,模m等于j的数的个数,那么最后的答案就是dp[(1<<n)-1][0].状态转移方程就是,dp[i|(1<< ...

  7. Travelling Salesman and Special Numbers CodeForces - 914C (数位dp)

    大意: 对于一个数$x$, 每次操作可将$x$变为$x$二进制中1的个数 定义经过k次操作变为1的数为好数, 求$[1,n]$中有多少个好数 注意到n二进制位最大1000位, 经过一次操作后一定变为1 ...

  8. Codeforces - 914C 数位DP

    题意有点难以描述,简略的就是给定一个二进制\(n\),每一步操作能使\(n\)的位为1的数的和转化为一个十进制,然后转化为该数的二进制再进行相同的操作 查询\([0,n]\)中操作数恰好为\(k\)的 ...

  9. Codeforces #55D (数位dp+离散化)

    Description Volodya is an odd boy and his taste is strange as well. It seems to him that a positive ...

  10. Codeforces 13C Sequence --DP+离散化

    题意:给出一个 n (1 <= n <= 5000)个数的序列 .每个操作可以把 n 个数中的某一个加1 或 减 1.问使这个序列变成非递减的操作数最少是多少 解法:定义dp[i][j]为 ...

随机推荐

  1. Centos 7 安装 sphinx2.2 (转)

    一.首先到Sphinx官网找到下载地址:http://sphinxsearch.com/downloads/release/如果你比较懒,好吧:http://sphinxsearch.com/file ...

  2. 配置阿里云的金融云上的rsync

    论坛里看到易淘发的教程, 转载过来

  3. setTimeout闭包常见问题

    经常会遇到这样的问题,setTimeout按序输出循环数字,而不是最后输出同一个数字: 题目: for (var i = 0; i < 5; i++) { setTimeout(function ...

  4. table布局与div布局

      DIV与TABLE本身并不存在什么优缺点,所谓web标准只是推荐的是正确的使用标签,好比说:DIV用于布局,而TABLE则本来就是转二维数据的.让TABLE做该做的事,并不是说页面里不出现TABL ...

  5. html:meta

    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale= ...

  6. ImportError: No module named etree.ElementTree问题解决方法

    学习python操作xml文档过程中碰到的ImportError: No module named etree.ElementTree问题,问题现象比较奇怪,做个记录. 操作环境 Python3.6+ ...

  7. zTree插件 角色、部门、人员分类选择

    // 传参数调用 function test(){roleOrOrgSelect(3,function(data){console.log(data);});} /** * * @param type ...

  8. 学JS的心路历程-Promise(二)

    昨天有说到Promise的创建以及then的用法,今天我们来看错误处理. then onRejected 我们昨天有提到说,then两个函式参数,onFulfilled和onRejected,而onR ...

  9. selenium自动化测试安装,浏览器驱动版本对应

  10. java的acm输入输出格式+大数语法

    1.类名称必须采用public class Main方式命名 2.多组输入,读取到文件尾 Scanner scan=new Scanner(System.in); while(scan.hasNext ...