CF55D Beautiful numbers 数位dp
Posted 20020723yjx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 "); //#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; }
以上是关于CF55D Beautiful numbers 数位dp的主要内容,如果未能解决你的问题,请参考以下文章
CF55D Beautiful numbers (数位dp)