测试地址:Beautiful Numbers
题目大意: 求在区间
中,有多少能整除自身全部非零数位的数。
作法: 本题须要用到数位DP+优化。
首先这题一看就是数位DP,本题的关键是状态的设计以及优化。
咱们很快能写出一个状态定义:
表示前
位,全部非零位的LCM是
,对
的余数是
,不卡/卡上界的数的数目。但咱们发现这个东西不能转移,当
增长的时候,新的余数会有不少种状况,所以咱们不能考虑这种状态定义。
咱们发现,涉及到的全部的
都是
的因数,因此咱们只须要
的表示改为对
的余数,那么
是
的整数倍时,就表示这些数知足题目中的条件。
这样咱们就能转移了。但分析一下发现,时间复杂度是
(位数)
(求LCM)
(枚举转移的位)
(数据组数),T到没边,所以咱们还要进一步进行优化。
打表或手算发现,不一样的
的数目,也就是
的因数,只有
个,所以用一个数组映射一下这些数,
用映射后的值表示便可,优化掉一个
。进而咱们发现咱们能够预处理出这些数之间的LCM,因此又优化掉了一个
。进行这两个优化后,已经很是接近时限了,但仍是会T掉。进一步观察发现,卡上界的状况中只有一个数,这个数的
是肯定的,不用跟随上面的枚举,所以咱们根本不用存
一维,只要维护当前上界的
便可完成应完成的转移。因此又优化掉了一个
,就能够经过此题了,最大点的时间为
左右。
如下是本人代码:html
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int LCM=2520; int T,n,s[20],lcmlist[1050],id[3010],L[50][10],tot; ll f[21][LCM+10][50]; int gcd(int a,int b) { return (b==0)?a:gcd(b,a%b); } int lcm(int a,int b) { return a*b/gcd(a,b); } ll solve() { memset(f[n+1],0,sizeof(f[n+1])); int toplcm=1,toprem=0; for(int i=n;i>=1;i--) { memset(f[i],0,sizeof(f[i])); for(int j=0;j<LCM;j++) for(int k=1;k<=tot;k++) for(int now=0;now<=9;now++) f[i][(j*10+now)%LCM][L[k][now]]+=f[i+1][j][k]; if (i<n) { for(int now=0;now<s[i];now++) f[i][(toprem*10+now)%LCM][L[toplcm][now]]++; } for(int j=1;j<=((i==n)?(s[i]-1):9);j++) f[i][j][id[j]]++; toplcm=L[toplcm][s[i]]; toprem=(toprem*10+s[i])%LCM; } ll ans=0; for(int i=1;i<=tot;i++) for(int j=0;j*lcmlist[i]<LCM;j++) ans+=f[1][j*lcmlist[i]][i]; if (toprem%lcmlist[toplcm]==0) ans++; return ans; } int main() { scanf("%d",&T); tot=0; for(int i=1;i<(1<<9);i++) { int x=1; for(int j=1;j<=9;j++) if ((1<<(j-1))&i) x=lcm(x,j); lcmlist[++tot]=x; } sort(lcmlist+1,lcmlist+tot+1); tot=0; for(int i=1;i<(1<<9);i++) if (i==1||lcmlist[i]!=lcmlist[tot]) { lcmlist[++tot]=lcmlist[i]; id[lcmlist[tot]]=tot; } for(int i=1;i<=tot;i++) for(int j=0;j<=9;j++) L[i][j]=id[lcm(lcmlist[i],max(j,1))]; while(T--) { ll x; scanf("%I64d",&x); x--; ll ans=0; if (x) { n=0; while(x) { s[++n]=x%10; x/=10; } ans-=solve(); } scanf("%I64d",&x); n=0; while(x) { s[++n]=x%10; x/=10; } ans+=solve(); printf("%I64d\n",ans); } return 0; }