CF55D Beautiful numbers

Posted sto324

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF55D Beautiful numbers相关的知识,希望对你有一定的参考价值。

题目描述

对于一个数,如果他能被任何一位上的数整除,那么他就是beautiful number,有t组询问求[l,r]的beautiful number。

1<=li?<=ri?<=91018

题解

看到没有一点思路,甚至想到上次做的数位DP想把[0,9]都开出一维,但是不仅空间过不去,而且不知道咋处理这个数没出现。

那么就去借鉴题解,lcm(???)

整除每一位就是整除出现过的数的lcm!!!

[1..9]的最小公倍数2520,出现过的数的lcm一定是2520的因数,所以只用判断x%2520是不是lcm的倍数即可,因为%相当于减法,那么-2520就是减多次lcm,就相当于%lcm只是最后的数在[0,2520)之间。

所以f[s][sum][lcm]表示当前第s位,%2520为sum,出现过的数的lcm

但是还是空间爆了,但是还是因为lcm是2520的因数,所以第三维只用开因数个数大小即可,同一个数组映射。

 

技术图片
#include<bits/stdc++.h>
using namespace std;

#define ll long long
const int mod=2520;
int t,cnt,mp[2530];
ll l,r;
ll f[20][2530][50];
int len,num[20];

int gcd(int a,int b)
    return !b ? a : gcd(b,a%b);


ll dfs(int s,int sum,int lcm,bool lim)
    if(!s) return !(sum%lcm);
    if(!lim&&f[s][sum][mp[lcm]]!=-1) return f[s][sum][mp[lcm]];
    int mx= lim ? num[s] : 9;
    ll ret=0;
    for(int i=0;i<=mx;i++)
     ret+=dfs(s-1,(sum*10+i)%mod,!i ? lcm : lcm/gcd(lcm,i)*i,lim&&i==mx);
    if(!lim) f[s][sum][mp[lcm]]=ret;
    return ret;


ll cx(ll x)
    len=0;
    while(x)
        num[++len]=x%10;
        x/=10;
    
    return dfs(len,0,1,true);


int main()
    for(int i=1;i<=mod;i++)
     if(!(mod%i)) mp[i]=++cnt;
    scanf("%d",&t);
    memset(f,-1,sizeof(f));
    while(t--)
        scanf("%I64d%I64d",&l,&r);
        printf("%I64d\n",cx(r)-cx(l-1));
    
CF55D Beautiful numbers

 

以上是关于CF55D Beautiful numbers的主要内容,如果未能解决你的问题,请参考以下文章

CF55D Beautiful numbers

CF55D Beautiful numbers (数位dp)

CF55D Beautiful numbers 数位dp

[CF55D]Beautiful numbers(数位dp,状态压缩)

CF 55D

数位DPCF55D Beautiful numbers