您的位置:首页 > 其它

CodeForces 55D Beautiful numbers(数位dp)

2017-01-21 00:12 423 查看
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).

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


这道题的题意是一个数,如果能够被他所有非0的各位数的数字整除的话,那么他就是一个beautiful numbers.
例如24,既能被2整除,也能被4整数。
然后求范围内的beautiful数有多少个,明显就是数位dp.
一个数能满足beautiful数的条件是什么呢。
其实就是这个数能够被他所有位数上的数字的lcm(最小公倍数)整除。
可是这个数太大怎么办,我们在记录的过程中明显数组的空间就不够大。需要想办法把它压缩。
我们就可以先算出最大的最小公倍数的大小(即1到9的最小公倍数)为2520.
那么我们一个数满足x%lcm(x)=0,(1)
并且2520%lcm(x)=0,(2)
(1)(2)式子合并得,x%2520%lcm(x)=0;
那么我们就可以把一个beautiful数的范围由9*10^18压缩到2520了。
dp[20][2520][2520](dp[i][j][k])表示长度为i,它的所有位数的lcm为j,且这个数对maxLcm取余为k的数的个数。
这里懂吧,只要满足对应的条件即可。
可是呢,这样子数组的内存占用就太大了,我们需要统计的是满足beautiful数条件的数的个数。
那么第二维我们就可以相对压缩,实际上满足的数(preNum%preLcm=0)也就48个,
所以只需要统计这些满足条件的,不满足条件的直接忽略不需要统计,这样子我们就可以来做题了。//这里需要好好想想为什么。


#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define MOD 1000000007
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define Pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define inf 0x3f3f3f3f
#define Pi 4.0*atan(1.0)

#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-12;
const int maxn = 36;
using namespace std;

inline int read(){
int x(0),f(1);
char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxLcm=2520;
ll dp[20][50][maxLcm+10];
int bit[20];
int Hash[maxLcm+10];
inline int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
inline int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
ll dfs(int pos,int preNum,bool flag,int preLcm)
{
if(pos==0){
return preNum%preLcm==0;
}
if(!flag&&~dp[pos][Hash[preLcm]][preNum]){
return dp[pos][Hash[preLcm]][preNum];
}
ll ret=0;
int x=flag?bit[pos]:9;
for(int i=0;i<=x;++i){
int curNum=(preNum*10+i)%maxLcm;
int curLcm=preLcm;
if(i){
curLcm=lcm(preLcm,i);
}
ret+=dfs(pos-1,curNum,flag&&i==bit[pos],curLcm);
}
if(!flag){
dp[pos][Hash[preLcm]][preNum]=ret;
}
return ret;
}
ll cacl(ll n)
{
int k=0;
while(n){
bit[++k]=n%10;
n/=10;
}
return dfs(k,0,true,1);
}
int main()
{
int k=0;
for(int i=1;i<=maxLcm;++i){
Hash[i]=k+=(maxLcm%i==0);
}
mes(dp,-1);
int t=read();
ll l,r;
while(t--){
scanf("%I64d%I64d",&l,&r);
printf("%I64d\n",cacl(r)-cacl(l-1));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: