CF 55D - Beautiful numbers(数位DP)

题意:

如果一个数能被自己各个位的数字整除,那么它就叫 Beautiful numbers。
求区间 [a,b] 中 Beautiful numbers 的个数。

分析:先分析出,2~9 的最大的最小公倍数是 2520({5,7,8,9}),先预处理出所有可能的最小公倍数m[c]

dp[i][d][c]表示长度i, 余数d,各位上的数的最小公倍数是m[c]的个数。

#include<cstdio>
#include<cstring>
#define mod 2520
ll dp[35][2520][100];
int bit[64],m[200],mnum;
int gcd(int a,int b){
    int tmp;
    while(a%b){
        tmp=b;
        b=a%b;
        a=tmp;
    }
    return b;
}
int lcm(int a,int b){
    return a*b/gcd(a,b);
}
//查最小公倍数的标号
int tfind(int x){ int ll=1,rr=mnum; while(ll<=rr){ int mid=(ll+rr)>>1; if(m[mid]<x)ll=mid+1; else rr=mid-1; } return ll; } void init(){ memset(dp,-1,sizeof(dp)); mnum=0; for(int i=1;i<=mod;++i) if(mod%i==0) m[++mnum]=i; } ll dfs(int i,int d,int c,int e){ if(i==0)return d%m[c]?0:1; if(!e&&dp[i][d][c]!=-1)return dp[i][d][c]; int l=e?bit[i]:9; ll num=0; for(int j=0;j<=l;++j) { int td=(d*10+j)%mod; int tc=c; if(j)tc=tfind(lcm(m[c],j)); num+=dfs(i-1,td,tc,e&&(j==l)); } return e?num:dp[i][d][c]=num; } ll solve(ll x){ int len=0; while(x){ bit[++len]=x%10; x/=10; } return dfs(len,0,1,1); } int main() { int t; scanf("%d",&t); init(); ll x,y; while(t--){ scanf("%I64d%I64d",&x,&y); printf("%I64d\n",solve(y)-solve(x-1)); } return 0; }

 

转载于:https://www.cnblogs.com/zsf123/p/4675475.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值