#include<cstdio> //code by Alphnia#include<cstring>#include<iostream>usingnamespacestd;#define N 50005#define ll long longlla,b;llf[15],ksm[15],p[15],now[15];lldfs(intu,intx,boolf0,boollim){// u 表示位數,f0 是否有前導零,lim 是否都貼在上限上if(!u){if(f0)f0=0;return0;}if(!lim&&!f0&&(~f[u]))returnf[u];llcnt=0;intlst=lim?p[u]:9;for(inti=0;i<=lst;i++){// 枚舉這位要填的數字if(f0&&i==0)cnt+=dfs(u-1,x,1,lim&&i==lst);// 處理前導零elseif(i==x&&lim&&i==lst)cnt+=now[u-1]+1+dfs(u-1,x,0,lim&&i==lst);// 此時枚舉的前幾位都貼在給定的上限上。elseif(i==x)cnt+=ksm[u-1]+dfs(u-1,x,0,lim&&i==lst);elsecnt+=dfs(u-1,x,0,lim&&i==lst);}if((!lim)&&(!f0))f[u]=cnt;// 只有不貼着上限和沒有前導零才能記憶returncnt;}llgans(lld,intdig){intlen=0;memset(f,-1,sizeof(f));while(d){p[++len]=d%10;d/=10;now[len]=now[len-1]+p[len]*ksm[len-1];}returndfs(len,dig,1,1);}intmain(){scanf("%lld%lld",&a,&b);ksm[0]=1;for(inti=1;i<=12;i++)ksm[i]=ksm[i-1]*10ll;for(inti=0;i<9;i++)printf("%lld ",gans(b,i)-gans(a-1,i));printf("%lld\n",gans(b,9)-gans(a-1,9));return0;}
#include<cstdio> //code by Alphnia#include<cstring>#include<iostream>usingnamespacestd;intx,y,dp[15][3],p[50];intpre(){memset(dp,0,sizeof(dp));dp[0][0]=1;for(inti=1;i<=10;i++){dp[i][0]=dp[i-1][0]*9-dp[i-1][1];dp[i][1]=dp[i-1][0];dp[i][2]=dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0];}}intcal(intx){intcnt=0,ans=0,tmp=x;while(x){p[++cnt]=x%10;x/=10;}boolflag=0;p[cnt+1]=0;for(inti=cnt;i;i--){// 從高到低枚舉數位ans+=p[i]*dp[i-1][2];if(flag)ans+=p[i]*dp[i-1][0];else{if(p[i]>4)ans+=dp[i-1][0];if(p[i]>6)ans+=dp[i-1][1];if(p[i]>2&&p[i+1]==6)ans+=dp[i][1];if(p[i]==4||(p[i]==2&&p[i+1]==6))flag=1;}}returntmp-ans;}intmain(){pre();while(~scanf("%d%d",&x,&y)){if(!x&&!y)break;x=min(x,y),y=max(x,y);printf("%d\n",cal(y+1)-cal(x));}return0;}
閲讀題面發現,如果將數字看成字符串,那麼這就是需要完成一個多模匹配,自然而然就想到 AC 自動機。普通數位 DP 中,先從高到低枚舉數位,再枚舉每一位都填什麼,在這道題中,我們也就自然地轉化為枚舉已經填好的位數,再枚舉此時停在 AC 自動機上的哪個節點,然後從當前節點轉移到它在 AC 自動機上的子節點。
#include<bits/stdc++.h> //code by Alphniausingnamespacestd;#define N 1505#define ll long long#define mod 1000000007intn,m;chars[N],c[N];intch[N][10],fail[N],ed[N],tot,len;voidinsert(){intnow=0;intL=strlen(s);for(inti=0;i<L;++i){if(!ch[now][s[i]-'0'])ch[now][s[i]-'0']=++tot;now=ch[now][s[i]-'0'];}ed[now]=1;}queue<int>q;voidbuild(){for(inti=0;i<10;++i)if(ch[0][i])q.push(ch[0][i]);while(!q.empty()){intu=q.front();q.pop();for(inti=0;i<10;++i){if(ch[u][i]){fail[ch[u][i]]=ch[fail[u]][i],q.push(ch[u][i]),ed[ch[u][i]]|=ed[fail[ch[u][i]]];}elsech[u][i]=ch[fail[u]][i];}}ch[0][0]=0;}llf[N][N][2],ans;voidadd(ll&x,lly){x=(x+y)%mod;}intmain(){scanf("%s",c);n=strlen(c);scanf("%d",&m);for(inti=1;i<=m;++i)scanf("%s",s),insert();build();f[0][0][1]=1;for(inti=0;i<n;++i){for(intj=0;j<=tot;++j){if(ed[j])continue;for(intk=0;k<10;++k){if(ed[ch[j][k]])continue;add(f[i+1][ch[j][k]][0],f[i][j][0]);if(k<c[i]-'0')add(f[i+1][ch[j][k]][0],f[i][j][1]);if(k==c[i]-'0')add(f[i+1][ch[j][k]][1],f[i][j][1]);}}}for(intj=0;j<=tot;++j){if(ed[j])continue;add(ans,f[n][j][0]);add(ans,f[n][j][1]);}printf("%lld\n",ans-1);return0;}