题目来源: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. 列表(list) 的 基本操作

    举例说明:names = ["zhangyang", "guyun", 'xiangpeng', ['alex','jack'], "xuliangc ...

  2. centos7 redis配置

    https://www.cnblogs.com/web424/p/6796993.html

  3. mysql每天凌晨0点准时启动taskeng.exe如何关闭

    MySQL弹出一个taskeng.exe. 内容如下:=====================Start Initialization====================mysql Instal ...

  4. java实现生成二维码

    package com.cn.test; import java.awt.Graphics2D; import java.awt.geom.AffineTransform; import java.a ...

  5. java实现解压zip文件,(亲测可用)!!!!!!

    项目结构: Util.java内容: package com.cfets.demo; import java.io.File; import java.io.FileOutputStream; imp ...

  6. DevExpress控件TExtLookupComboBox实现多列模糊匹配输入的方法

    本方案不需要修改控件源码,是完美解决支持多列模糊匹配快速输入的最佳方案!!   1.把列的Properties属性设置为ExtLookupComboBox. Properties.Incrementa ...

  7. 向SqlParameter内动态添加参数

    动态向SqlParameter 里添加相应参数,方法如下 先定义一个List,然后再往List里面添加SqlParameter对象,然后将List转为SqlParameter数组即可 List< ...

  8. python语言中的数据类型之字典

    数据类型 字典类型dict 用途:记录多个值,列表是索引对应值,而字典是key对应值,其中key对value有描述性 定义方式:在{ }用逗号分隔开多个元素,每个元素都是key:value形式,其中k ...

  9. eclipse打断点,进行弹窗提示后点击是才进入debug视图,这个要怎么恢复

    window --> preferences --> Run/Debug --> Perspectives 里的 open the associated perspective wh ...

  10. ReactiveX 学习笔记(15)使用 Rx.NET + Json.NET 调用 REST API

    JSON : Placeholder JSON : Placeholder (https://jsonplaceholder.typicode.com/) 是一个用于测试的 REST API 网站. ...