Codeforces Beta Round #51 D. Beautiful numbers(数位dp)

7 篇文章 0 订阅
4 篇文章 0 订阅

题目链接

问区间[L,R] 之间有多少个数满足,这个数能够整除这个数的每一个数位,比如36可以整除3和6,所以是符合要求的数字。

直接看来,一个数每一位还没有确定的时候,就无法知道这个数能不能整除自己的每一位。

假如这个数是可以整除自己的每一位,也就是说这个数是自己每一位的公倍数,比如一个满足的数X组成是abc的形式,那么X是a的倍数,b的倍数,c的倍数,也就是X%lcm(a,b,c)==0。然后1-9的lcm是2520,也就是2520能整除1-9的任意组合,利用这些性质,就可以进行空间的压缩离散

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define LL long long
#define gcd __gcd
#define LCM(x,y) x/gcd(x,y)*y
#define dbg(x) printf("deg: # ::: %d\n",x);
#define cl(a,b) memset(a,b,sizeof(a))
const int maxn = 1005;
LL dp[20][2521][50];
int Lcm[2521];//离散 保证dp可以开下空间
int bit[20];
void init(){
    for(int i=1,j=0;i<=2520;i++)if(2520%i==0)
        Lcm[i]=j++;
}
LL dfs(int i,int s,int lm,bool e){
    if(i == 0) return s % lm== 0;
    if(!e && ~dp[i][s][Lcm[lm]]) return dp[i][s][Lcm[lm]];
    LL ans = 0;
    int u = e?bit[i]:9;
    for(int d=0;d<=u;d++){
        ans+=dfs(i-1,(s*10+d)%2520,d?LCM(lm,d):lm,e&&d==u);
    }
    return e?ans:dp[i][s][Lcm[lm]]=ans;
}
LL f(LL num){
    int len=0;
    while(num){
        bit[++len]=num%10;
        num/=10;
    }
    return dfs(len,0,1,1);
}

int main(){
    int T;init();
    scanf("%d",&T);cl(dp,-1);
    while(T--){
        LL L,R;scanf("%lld%lld",&L,&R);
        printf("%lld\n",f(R)-f(L-1));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值