CF 55D 数位dp(一个数是组成它的所有位数对应数的倍数)
来源:互联网 发布:淘宝店铺密码修改 编辑:程序博客网 时间:2024/05/17 02:16
http://codeforces.com/problemset/problem/55/D
/**CF 55D 数位dp(一个数是组成它的所有位数对应数的倍数)题目大意:找出给定区间内有多少数,其本身是所有组成它的各个位上的数的倍数解题思路:(kuangbin)一个数能被它的所有非零数位整除,则能被它们的最小公倍数整除,而1到9的最小公倍数为2520, 数位DP时我们只需保存前面那些位的最小公倍数就可进行状态转移,到边界时就把所有位的lcm求出了, 为了判断这个数能否被它的所有数位整除,我们还需要这个数的值,显然要记录值是不可能的,其实我们只 需记录它对2520的模即可,这样我们就可以设计出如下数位DP:dfs(pos,mod,lcm,f),pos为当前 位,mod为前面那些位对2520的模,lcm为前面那些数位的最小公倍数,f标记前面那些位是否达到上限, 这样一来dp数组就要开到19*2520*2520,明显超内存了,考虑到最小公倍数是离散的,1-2520中可能 是最小公倍数的其实只有48个,经过离散化处理后,dp数组的最后一维可以降到48,这样就不会超了。*/#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>using namespace std;const int mod=2520;typedef long long LL;LL dp[25][mod][50];int index[2530],bit[25];int gcd(int a,int b){ if(b==0)return a; else return gcd(b,a%b);}int lcm(int a,int b){ return a/gcd(a,b)*b;}void init(){ int num=0; for(int i=1; i<=mod; i++) { if(mod%i==0) index[i]=num++; }}LL dfs(int pos,int presum,int prelcm,bool flag){ if(pos==-1)return presum%prelcm==0; if(!flag&&dp[pos][presum][index[prelcm]]!=-1) return dp[pos][presum][index[prelcm]]; LL ans=0; int end=flag?bit[pos]:9; for(int i=0; i<=end; i++) { int nowsum=(presum*10+i)%mod; int nowlcm=prelcm; if(i)nowlcm=lcm(nowlcm,i); ans+=dfs(pos-1,nowsum,nowlcm,flag&&i==end); } if(!flag)dp[pos][presum][index[prelcm]]=ans; return ans;}LL solve(LL x){ int len=0; while(x) { bit[len++]=x%10; x/=10; } return dfs(len-1,0,1,1);}int main(){ int T; init(); memset(dp,-1,sizeof(dp)); scanf("%d",&T); while(T--) { LL r,l; scanf("%I64d%I64d",&l,&r); printf("%I64d\n",solve(r)-solve(l-1)); } return 0;}
0 0
- CF 55D 数位dp(一个数是组成它的所有位数对应数的倍数)
- CodeForces 55D 数位DP 能被它自身数位上的所有数整除
- CF 55D 离散化各个位数的倍数
- 1 .设N是一个四位数,它的9倍恰好是其反序数(例如:123的反序数是321),求N的值。
- /*设N是一个四位数,它的9倍恰好是其反序数(例如:123的反序数是321),求N的值.*/
- 编程题--任意给出一个四位数, 把它重新组成一个四位的最大数和一个最小数, 算出两者间的差
- 任意给出一个四位数, 把它重新组成一个四位的最大数和一个最小数, 算出两者间的差.
- 找出所有满足如下条件的六位数:它是一个完全平方数(即为某个整数的平方);该数同时也是回文数(即该数等于它的逆序数)。(C++上机考试题2)
- 设N是一个四位数,它的 9 倍恰好是其反序数,求N的值。
- 项目39.3-1输入一个正整数,输出它的反序数(反序数,即将其所有位的数字反过来。例如,123是321的反序数)
- D-数圈圈(数位dp)
- 在数组中找出一个数,这个数>=它前面的所有数,<它后面的所有数
- bin巨的数(数位DP)
- ccf 有趣的数(数位dp)
- CCF-有趣的数(数位DP)
- 数位dp cf 55d
- CF 55D 数位dp
- CF 55D 数位DP
- 快速排序(Quicksort)
- 程序的处理步骤——预处理、编译、链接、运行
- 为什么android的流畅度一直不出IOS?
- 【hibernate框架】继承映射
- Linux 用户操作
- CF 55D 数位dp(一个数是组成它的所有位数对应数的倍数)
- maven 下struts 框架搭建(系列一)
- file标签之查询数据库中的内容保存到文件
- leetcode--Reverse Nodes in k-Group
- 安卓开发教程 - 搭建开发环境
- [课程] 物联网导论
- POJ 3398 / UVA 1218 Perfect Service 树形DP
- 【hibernate框架】练习-树状结构设计(非常重要)
- Java—用实例揭示notify()和notifyAll()的本质区别