Beautiful numbers CodeForces

#include<iostream>
#include<cstring>
#include<cstdio> 
using namespace std;
typedef long long ll;
const int MOD=2520;
ll gcd(ll a,ll b) {
	return b==0?a:gcd(b,a%b);
}
ll lcm(ll a,ll b) {
	return a*b/gcd(a,b);
}
ll dp[30][MOD][50];
ll a[30],Hash[MOD];
ll DFS(int pos,int presum,int prelcm,int limit) {
	//到最后以为 
	if(pos==0)
		//当前值 % 出现过的数字的最小公倍数 
		return presum%prelcm==0;
	if(!limit&&dp[pos][presum][Hash[prelcm]]!=-1)
		return dp[pos][presum][Hash[prelcm]];
	int up=limit?a[pos]:9;
	ll res=0;
	for(int i=0; i<=up; i++) {
		int nowsum=(presum*10+i)%MOD;//可以对MOD任意取模而不影响结果
		int nowlcm=prelcm;
		if(i!=0)
			//求出现过的数字的最小公倍数 
			nowlcm=lcm(prelcm,i);
		res+=DFS(pos-1,nowsum,nowlcm,limit&&i==up);
	}
	if(!limit)
		dp[pos][presum][Hash[prelcm]]=res;
	return res;
}
ll solve(ll n) {
	int top=0;
	while(n) {
		a[++top]=n%10;
		n/=10;
	}
	return DFS(top,0,1,1);
}
void Init() {
	int cnt=0;
	for(int i=1; i<=2520; i++) { 
		if(MOD%i==0)
			Hash[i]=cnt++;
	}
}
int main() {
	ios::sync_with_stdio(0);
	Init();
	int T;
	memset(dp,-1,sizeof(dp));
	cin>>T;
	while(T--) {
		ll l,r;
		cin>>l>>r;
		cout<<solve(r)-solve(l-1)<<endl;
	}
	return 0;
}

原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12500775.html