CF55D Beautiful numbers 数位dp

恢复魔芋本质,,改了1h+,,

题目传送门

其实这个题挺水的。也就我这种忘了%大佬的蒟蒻要调这么久。

首先,我们要找的是能被每一位整除的数。处理成1~R的答案  -  1~(l-1)的答案。

从最高位开始搜索放啥。如果已经是最后一位了,且当前数能被当前各位的最小公倍数整除,它就是一个合法的方案。那么,将长度,当前和,当前lcs,是否有限制带着搜就行了。

注意,因为每一位只有1~9,这里的不同lcs最多不到50个,预处理离散化一下即可。

还有就是本组数据结束的时候要把有限制的清空,无限制的保留(最早我全留着,果断挂得一分不剩),然后就是因为1~9的lcs为2520,所以每次的和对2520取模并无影响。然后,诶,又可以A了耶。

#include<bits/stdc++.h>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<deque>
#include<list>
#include<set>
#include<vector>
#include<iostream>
#define ll long long
#define re register
#define inf 0x3f3f3f3f
#define inl inline
#define sqr(x) (x*x)
//#define eps 1e-8
#define debug printf("debug\n");
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#pragma GCC optimize (2)
//#pragma G++ optimize (2)
using namespace std;
const ll mod=2520;
const ll MAXN=5e4+10;
const ll MAXM=(5e4+10)*4;
inl ll read() {
    re ll x = 0; re int f = 1;
    char ch = getchar();
    while(ch<'0'||ch>'9') { if(ch== '-' ) f = -1; ch = getchar(); }
    while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x * f;
}
inl char readc() {
    char ch=getchar();
    while(('z'<ch||ch<'a')&&('Z'<ch||ch<'A')) ch=getchar();
    return ch;
}
inl void write(re ll x){
    if(x>=10)write(x/10);
    putchar(x%10+'0');
}
inl void writeln(re ll x){
    if(x<0) {x=-x;putchar('-');}
    write(x); puts("");
}
inl ll gcd(re ll x,re ll y){while(y^=x^=y^=x%=y);return x;}
inl ll Lcm(re ll a,re ll b) {return a/gcd(a,b)*b;}
inl void FR() {
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
}
inl void FC() {
    fclose(stdin);
    fclose(stdout);
}
ll a[25],top,indx[5005],dp[25][5005][50];
ll dfs(ll len,ll pre,ll lcm,bool limit) {
    if(!len) return (!(pre%lcm));
    if(!limit&&~dp[len][pre][indx[lcm]]) return dp[len][pre][indx[lcm]];
    ll num=limit?a[len]:9;
    ll ans=0;
    for(re ll i=0;i<=num;i++) {
        re ll nowsum,nowlcm=lcm;
        nowsum=((pre<<3)+(pre<<1)+i)%mod;
        if(i) nowlcm=Lcm(nowlcm,i);
        ans+=dfs(len-1,nowsum,nowlcm,limit&&i==num);
    }
    if(!limit) dp[len][pre][indx[lcm]]=ans;
    return ans;
}
ll calc(ll x) {
    top=0;
    while(x) {
        a[++top]=x%10;
        x/=10;
    }
    return dfs(top,0,1,1);
}
int main() {
//  FR();
    re ll t=read();
    memset(dp,-1,sizeof(dp));
    for(re ll i=1,tot=0;i<=2520;i++) {
        if(!(mod%i)) indx[i]=++tot;
    }
    while(t--) {
        re ll l=read(),r=read();
        writeln(calc(r)-calc(l-1));
    }
//  FC();
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/20020723YJX/p/9385898.html
今日推荐