1. 程式人生 > >4521: [Cqoi2016]手機號碼

4521: [Cqoi2016]手機號碼

比較基本的數位DP,限制都較為簡單;

#include<bits/stdc++.h>
#define rep(i,k,n) for(int i=k;i<=n;i++)
#define rep2(i,k,n) for(int i=k;i>=n;i--)
using namespace std;
typedef long long ll;
const int N=13;
void upd(ll& x,ll y){x+=y;}
ll f[N][N][3][3][2][2],L,R,a[N],top;
//f[位][首位][連續][4,8][是否已經有連續的三個][上界0,1]
ll solve(ll x){ memset(f,0,sizeof(f)); top=0;for(;x;a[++top]=x%10,x/=10); rep(i,0,9)f[0][i][0][0][0][0]=f[0][i][0][0][0][1]=1; rep(i,0,top-1){ rep(now,0,9){ rep(ne,0,9){ int op=(ne==now); int ss=(ne==4)|((ne==8)<<1); rep(len,0,2
){ if(!len && !op)continue; int ok=((len==2) && op); if(len==2 && !op)op=-1; rep(s,0,2){ if((ss|s)==3)continue; rep(_3,0,1){ ll res0=f[i][now][len][s][_3][0
]; ll res1=f[i][now][len][s][_3][1]; ll& goal0=f[i+1][ne][min(2,len+op)][ss|s][_3|ok][0]; ll& goal1=f[i+1][ne][min(2,len+op)][ss|s][_3|ok][1]; upd(goal0,res0); if(ne<a[i+1])upd(goal1,res0); else if(ne==a[i+1])upd(goal1,res1); } } } } } } ll ans=0; rep(i,0,9)rep(len,0,2)rep(s,0,2)upd(ans,f[top][i][len][s][1][1]); return ans; } int main(){ scanf("%lld%lld",&L,&R); ll lim=10000000000; ll res1=solve(R); ll res2=solve(max(lim,L-1)); printf("%lld\n",res1-res2+(L==lim)); }