CF55D Beautiful numbers
Posted sto324
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF55D Beautiful numbers相关的知识,希望对你有一定的参考价值。
题目描述
对于一个数,如果他能被任何一位上的数整除,那么他就是beautiful number,有t组询问求[l,r]的beautiful number。
1<=li?<=ri?<=9⋅1018
题解
看到没有一点思路,甚至想到上次做的数位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 (数位dp)