题目来源: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. 彻底关闭Windows Defender丨Win10

    关闭Windows Defender Win10正式版怎么关闭windows defender 首先关闭windows defender,因重启电脑后win10 会自动重启defender,所以需要禁 ...

  2. ACM__菜鸟之经典错误

    1:多组输入与单组输入 Input contains multiple test cases. Input contains a single test case. 2:  EOF=-1 while( ...

  3. 为什么java实体类需要重写toString方法

    如果没重写toString的情况: Object 类的 toString 方法 返回一个字符串,该字符串由类名(对象是该类的一个实例).at 标记符“@”和此对象哈希码的无符号十六进制表示组成.换句话 ...

  4. TypeScript set get

    private _id:number; public get id():number{ return this._id; } public set id(value:number){ this._id ...

  5. mac使用brew安装sshpass

    brew安装sshpass brew install https://raw.githubusercontent.com/kadwanev/bigboybrew/master/Library/Form ...

  6. 火狐的3d视图插件Tilt 3D

    15年的时候,使用过此功能.后来没注意就发现没了.firefox在47之后就停止自带了. 换成插件了. https://addons.mozilla.org/en-US/firefox/addon/t ...

  7. 国内Maven仓库 - 2018年5月2日15:54:10

    <mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> & ...

  8. curl命令解析

    curl命令可以实现http post或者get的请求,是linux下的命令行工具 1.1.直接请求url,打印标准输出 1.2.使用-o参数,可以标准输出到指定的位置 [root@VM-3-10-1 ...

  9. ArcGIS(ESRI)的发展历史和版本历史(简介)

    作者:fenghuayoushi 来源:CSDN 原文:https://blog.csdn.net/fenghuayoushi/article/details/6677360   ESRI公司介绍   ...

  10. 头像修改功能 包含ios旋转图片 但是旋转后没遮罩, 正常图片可以显示遮罩 宽高不规则图片没做控制 遮罩框可以拖动

    https://blog.csdn.net/wk767113154/article/details/77989544  参考资料 <template> <div id="p ...