$CF55D [数位DP]$
数位DP+状压。
首先,按照数位DP的基本套路,每个个位数的最小公倍数为2520,所以只用考虑模2520的情况。考虑一个DP。dp[i][j][k]表示当前是第i位,2~9的数的集合为j,模2520为k的方案数。然后,就是数位DP的基本套路解决这道题。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
inline LL read () {
LL res = 0 ;
int f (1) ;
char ch = getchar ();
while (!isdigit(ch)) {
if (ch == '-') f = -1 ;
ch = getchar();
}
while (isdigit(ch)) res = (res << 1) + (res << 3) + (ch ^ 48),ch = getchar();
return res * f ;
}
const int N=20;
const int mod=2520;
int p[49]= {0,1,2,3,4,5,6,7,8,9,10,12,14,15,18,20,21,24,28,
30,35,36,40,42,45,56,60,63,70,72,84,90,105,120,126,140,168,
180,210,252,280,315,360,420,504,630,840,1260,2520
};
int _lcm(int m,int n) {
return (m*n)/__gcd(m, n);
}
LL f[N][49][mod+2], bit[N], has[mod+2];
inline LL dfs(int i,int lcm,int left, bool e) {
if(i==0) return lcm&&left%p[lcm]==0 ;
if(!e && ~f[i][lcm][left]) return f[i][lcm][left];
LL ans=0;
int u= e? bit[i]: 9;
for(register int d=0; d<=u; d++) {
int t= lcm? has[_lcm(p[lcm], max(d,1))]: max(d,0);
ans+=dfs(i-1, t, (left*10+d)%mod, e&&d==u);
}
return e==true? ans: f[i][lcm][left]=ans;
}
LL cal(LL n) {
int len=0;
while(n) {
bit[++len]=n%10;
n/=10;
}
return dfs(len,0,0,true);
}
signed main() {
ios::sync_with_stdio(false);
memset(f,-1,sizeof(f));
for(register int i=0; i<49; i++) has[p[i]]=i;
LL t=read();
while( t-- ) {
LL L=read(),R=read();
cout<<cal(R)-cal(L-1)<<endl;
}
return 0;
}
跑的好慢啊QwQ
不存在十全十美的文章 如同不存在彻头彻尾的绝望