BZOJ 4521 手机号码 数位dp
题解:开个6维的dp函数,第一维记录位置,第二维记录当前位置的前两个,第三维记录当前位置的前一个,第四维记录是否出现4,第五位记录是否出现8,第六维记录是否满足出现三个连续的数字。特判1e10
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <map> #include <queue> #include <vector> #include <cstring> #include <iomanip> #include <set> #include<ctime> //#include<unordered_map> //CLOCKS_PER_SEC #define se second #define fi first #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define Pii pair<int,int> #define Pli pair<ll,int> #define ull unsigned long long #define pb push_back #define fio ios::sync_with_stdio(false);cin.tie(0) const int N=100; const ull base=163; const int INF=0x3f3f3f3f; using namespace std; int a[N]; ll dp[20][20][20][2][2][2]; ll dfs(int pos,int pre1,int pre2,bool lead,bool limit,bool flag,bool op,bool oo){//op--4 oo-8 if(op&&oo)return 0; if(pos==-1)return flag==1; if(!lead&&!limit&&dp[pos][pre1][pre2][op][oo][flag]!=-1)return dp[pos][pre1][pre2][op][oo][flag]; int up=limit?a[pos]:9; ll tmp=0; for(int i=lead?1:0;i<=up;i++){ if(!flag){ int io=0; if(pre1==pre2&&i==pre2)io=1; tmp+=dfs(pos-1,pre2,i,0,limit&&i==a[pos],io,op||i==4,oo||i==8); } else{ tmp+=dfs(pos-1,pre2,i,0,limit&&i==a[pos],flag,op||i==4,oo||i==8); } } if(!limit)dp[pos][pre1][pre2][op][oo][flag]=tmp; return tmp; } ll solve(ll x){ int pos=0; while(x){ a[pos++]=x%10; x/=10; } return dfs(pos-1,10,10,true,true,0,0,0); } int main(){ ll a,b; cin>>a>>b; memset(dp,-1,sizeof(dp)); printf("%lld\n",a==10000000000?solve(b):solve(b)-solve(a-1)); return 0; }