具体的dp不用说。
注意有个问题:有很多状态是0,但其实是访问到了的。所以一开始要memset为-1才不会T那个最大的点。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 3050 using namespace std; int t,a[maxn],hash[maxn],tot=0,bit[30],times=0,ret=0; long long l,r,dp[20][maxn][50]; int gcd(int a,int b) { if (!b) return a; return gcd(b,a%b); } void get_table() { for (int i=1;i<=2520;i++) if (2520%i==0) a[++tot]=i; for (int i=1;i<=tot;i++) hash[a[i]]=i; } void ask_bit(long long x) { ret=0; while (x) { bit[++ret]=(int)(x%10); x/=10; } } long long dps(int pos,int mod,int l,bool flag) { if (!pos) return mod%l==0; long long &f=dp[pos][mod][hash[l]]; if (flag && f!=-1) return f; int lim=flag?9:bit[pos];long long ans=0; for (int i=0;i<=lim;i++) ans+=dps(pos-1,(mod*10+i)%2520,i?l*i/gcd(l,i):l,flag|(i<lim)); return flag?f=ans:ans; } long long work(long long x) {ask_bit(x);return dps(ret,0,1,0);} int main() { scanf("%d",&t);get_table();memset(dp,-1,sizeof(dp)); for (int i=1;i<=t;i++) { scanf("%lld%lld",&l,&r); printf("%lld ",work(r)-work(l-1)); } return 0; }