CF55D Beautiful numbers

R e s u l t Result Result

...


H y p e r l i n k Hyperlink Hyperlink

https://www.luogu.com.cn/problem/CF55D


D e s c r i p t i o n Description Description

一个数能被自己每一非0位上的数整除的数是很美妙的
[ L , R ] [L,R] [L,R]的美妙数个数

数据范围: L ≤ R ≤ 9 × 1 0 18 L\leq R\leq 9\times 10^{18} LR9×1018


S o l u t i o n Solution Solution

数位 d p dp dp,设 f r e s t , s u m , m o d f_{rest,sum,mod} frest,sum,mod表示剩余 r e s t rest rest位,当前的数是 s u m sum sum,能整除的有关1~9的数为 m o d mod mod

对于第二维,显然我们只关心每个数对0~9的乘积,所以只需要关心它对 l c m ( 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ) = 2520 lcm(1,2,3,4,5,6,7,8,9)=2520 lcm(1,2,3,4,5,6,7,8,9)=2520取模的结果
对于第三维,显然我们只关心它是 m o d mod mod的哪个约数(即它能整除1~9的哪些数,不一定具体,但要能表示)

建立记忆化搜索 d f s ( r e s t , s u m , m o d , l i m i t ) dfs(rest,sum,mod,limit) dfs(rest,sum,mod,limit)
然后有 r e s + = d f s ( r e s t − 1 , ( 10 s u m + i ) % 2520 , i = = 0 ? m o d : l c m ( m o d , i ) , l i m i t & i = = c a n c s e ) res+=dfs(rest-1,(10sum+i)\%2520,i==0?mod:lcm(mod,i),limit\& i==cancse) res+=dfs(rest1,(10sum+i)%2520,i==0?mod:lcm(mod,i),limit&i==cancse)


C o d e Code Code

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int a[20],m,T,ys[2521],cnt;
LL f[20][2520][50],l,r;
inline LL read()
{
	char c;LL d=1,f=0;
	while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
inline LL gcd(LL x,LL y){return y?gcd(y,x%y):x;}
inline LL lcm(LL x,LL y){return x*y/gcd(x,y);}
inline LL dfs(int rest,int sum,int mod,bool limit)
{
	if(rest==0) return sum%mod==0;
	if(limit==0&&f[rest][sum][ys[mod]]!=-1) return f[rest][sum][ys[mod]];
	int cancse=limit?a[rest]:9;
	LL res=0;
	for(register int i=0;i<=cancse;i++) res+=dfs(rest-1,(sum*10+i)%2520,i==0?mod:lcm(mod,i),limit&&i==cancse);
	if(limit==0) f[rest][sum][ys[mod]]=res;
	return res;
}
inline LL solve(LL x) 
{
	m=0;
	while(x) {a[++m]=x%10;x/=10;}
	return dfs(m,0,1,1);
}
signed main()
{
	memset(f,-1,sizeof(f));
	for(register int i=1;i*i<=2520;i++) if(2520%i==0) ys[i]=++cnt,ys[2520/i]=++cnt;
	T=read();
	while(T--)
	{
		l=read();r=read();
		printf("%lld\n",solve(r)-solve(l-1));
	}
}
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页