測試地址: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; }