CodeForces - 55D(数位dp,离散化)
题目来源: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).
1
1 9
9
1
12 15
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,离散化)的更多相关文章
- Codeforces 55D (数位DP+离散化+数论)
题目链接: http://poj.org/problem?id=2117 题目大意:统计一个范围内数的个数,要求该数能被各位上的数整除.范围2^64. 解题思路: 一开始SB地开了10维数组记录情况. ...
- codeforces 55D 数位dp
D. Beautiful numbers time limit per test 4 seconds memory limit per test 256 megabytes input standar ...
- CodeForces 55D "Beautiful numbers"(数位DP+离散化处理)
传送门 参考资料: [1]:CodeForces 55D Beautiful numbers(数位dp&&离散化) 我的理解: 起初,我先定义一个三维数组 dp[ i ][ j ][ ...
- codeforces 55D - Beautiful numbers(数位DP+离散化)
D. Beautiful numbers time limit per test 4 seconds memory limit per test 256 megabytes input standar ...
- Codeforces 628D 数位dp
题意:d magic number(0<=d<9)的意思就是一个数,从最高位开始奇数位不是d,偶数位是d 题目问,给a,b,m,d(a<=b,m<2000)问,a,b之间有多少 ...
- codeforces 401D (数位DP)
思路:很明显的数位dp,设dp[i][j] 表示选取数字的状态为i,模m等于j的数的个数,那么最后的答案就是dp[(1<<n)-1][0].状态转移方程就是,dp[i|(1<< ...
- Travelling Salesman and Special Numbers CodeForces - 914C (数位dp)
大意: 对于一个数$x$, 每次操作可将$x$变为$x$二进制中1的个数 定义经过k次操作变为1的数为好数, 求$[1,n]$中有多少个好数 注意到n二进制位最大1000位, 经过一次操作后一定变为1 ...
- Codeforces - 914C 数位DP
题意有点难以描述,简略的就是给定一个二进制\(n\),每一步操作能使\(n\)的位为1的数的和转化为一个十进制,然后转化为该数的二进制再进行相同的操作 查询\([0,n]\)中操作数恰好为\(k\)的 ...
- Codeforces #55D (数位dp+离散化)
Description Volodya is an odd boy and his taste is strange as well. It seems to him that a positive ...
- Codeforces 13C Sequence --DP+离散化
题意:给出一个 n (1 <= n <= 5000)个数的序列 .每个操作可以把 n 个数中的某一个加1 或 减 1.问使这个序列变成非递减的操作数最少是多少 解法:定义dp[i][j]为 ...
随机推荐
- mysql Lock wait timeout exceeded; try restarting transaction解决
前面已经了解了InnoDB关于在出现锁等待的时候,会根据参数innodb_lock_wait_timeout的配置,判断是否需要进行timeout的操作,本文档介绍在出现锁等待时候的查看及分析处理: ...
- python redis客户端使用lua脚本
有一个需求,为一个key设置一个field存储时间戳,每当有新数据,判断新数据时间戳是否大于之前的时间戳,如果是,更新时间戳,由于依赖中间执行结果,所以使用lua减少客户端和服务端通信次数. #!/u ...
- django403错误(转)
原文:http://blog.sina.com.cn/s/blog_60ccc6e101011ku0.html 处理过程 1.按提示及google结果修改setting.py,在MIDDLEWARE_ ...
- linux command>file 2>&1 & 命令详解
command>file >& & 命令的最后一个&表示把该命令以后台的job的形式运行 一个命令的执行伴随着三种输入输出 标准输入(stdin):默认指向键盘的输 ...
- C# 模拟鼠标操作
[Flags] enum MouseEventFlag : uint //设置鼠标动作的键值 { Move = 0x0001, //发生移动 LeftDown = 0x0002, //鼠标按下左键 L ...
- [namespace]PHP命名空间的使用基础
-------------------------------------------------------------------------------------------------- 一 ...
- Structs复习 Action
引入jar包 web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version= ...
- android布局管理器
1 LinearLayout (线性布局) 让所有的组件都成为单一的方向,机垂直的或水平的(默认). android:Layout_weight //该属性控制水平和垂直方向某个控件所占比例. 2.F ...
- Hosts
Hosts "C:\Windows\System32\drivers\etc\hosts" [最新]2018 hosts 持续更新[更新于:2018-11-13] 本页面WordP ...
- 吴裕雄 09-MySQL删除数据表
以下为删除MySQL数据表的通用语法:DROP TABLE table_name; DROP TABLE runoob_tbl; 使用PHP脚本删除数据表PHP使用 mysqli_query 函数来删 ...