数位dp-CF55D

#include<bits/stdc++.h>
using namespace std;
const int MAXN=2520+5;
typedef long long LL;
int Hash[MAXN],bit[20];
LL dp[20][50][MAXN];

int gcd(int a,int b) {return b==0?a:gcd(b,a%b);}
int lcm(int a,int b) {return a/gcd(a,b)*b;}

LL dfs(int pos,int prelcm,int prenum,int limit){
    if(pos==0) return prenum%prelcm==0;
    if(!limit&&dp[pos][Hash[prelcm]][prenum]!=-1)
        return dp[pos][Hash[prelcm]][prenum];
    int num=limit?bit[pos]:9;
    LL res=0;
    for(int i=0;i<=num;i++){
        int nowlcm=prelcm;
        if(i) nowlcm=lcm(prelcm,i);
        int nownum=(prenum*10+i)%2520;
        res+=dfs(pos-1,nowlcm,nownum,limit&&(i==num));
    }
    if(!limit) dp[pos][Hash[prelcm]][prenum]=res;
    return res;
}

LL solve(LL n){
    int len=0;
    while(n){
        bit[++len]=n%10;
        n/=10;
    }
    return dfs(len,1,0,1);
}

int main(){
    int c=0;
    for(int i=1;i<=2520;i++){
        if(2520%i==0) Hash[i]=++c;
    }
    memset(dp,-1,sizeof(dp));
    int T;
    scanf("%d",&T);
    while(T--){
        LL l,r;
        scanf("%I64d%I64d",&l,&r);
        printf("%I64d\n",solve(r)-solve(l-1));
    }
    return 0;
}
/*
1
1 9000000000000000000
15957349671845566
*/

猜你喜欢

转载自blog.csdn.net/algzjh/article/details/81431300