P4124 [CQOI2016]手机号码
P4124 [CQOI2016]手机号码
题解
数位DP DFS 虽然套路,但还是恶心到找不到锅在哪里
注意这个
然后你就发现其实这样就不用记录前导0了
锅在这个鬼地方QAQ
代码
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<queue> using namespace std; typedef long long ll; inline ll read() { ll ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } ll l,r; ll c[15],len=0; ll dp[15][15][15][2][2][2]; ll dfs(ll pos,ll pre,ll ppre,bool have8,bool have4,bool have,bool limit,bool qdl) //当前填到了第几位, 前一位是啥, 前前位是啥, 有没有8, 有没有4, 有没有连续相等的至少3个数, 有没有顶上界, 是不是全都是前导0 { if(have8&&have4) return 0; if(pos<=0) return have; if(!limit&&!qdl&&dp[pos][pre][ppre][have8][have4][have]!=-1) return dp[pos][pre][ppre][have8][have4][have]; ll ans=0; ll up=limit?c[pos]:9; for(ll i=(pos==len);i<=up;i++) //注意这里,如果是第一位就不能填0,要从1填起 ans+=dfs(pos-1,i,pre, have8||(i==8),have4||(i==4), have||((i==pre)&&(i==ppre)), limit&&(i==up),qdl&&(i==0)); if(!limit&&!qdl) dp[pos][pre][ppre][have8][have4][have]=ans; return ans; } ll sum(ll x) { if(x<1e10||x>=1e11) return 0; memset(c,0,sizeof(c));len=0; while(x) { c[++len]=x%10; x/=10; } memset(dp,-1,sizeof(dp)); return dfs(len,-1,-1,0,0,0,1,1); } int main() { l=read();r=read(); if(l>r) { printf("0\n"); return 0; } printf("%lld\n",sum(r)-sum(l-1)); return 0; }
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<queue> using namespace std; typedef long long ll; inline ll read() { ll ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } ll l,r; ll c[15],len=0; ll dp[15][15][15][2][2][2]; ll dfs(ll pos,ll pre,ll ppre,bool have8,bool have4,bool have,bool limit) { if(have8&&have4) return 0; if(pos<=0) return have; if(!limit&&dp[pos][pre][ppre][have8][have4][have]!=-1) return dp[pos][pre][ppre][have8][have4][have]; ll ans=0; ll up=limit?c[pos]:9; for(ll i=(pos==len);i<=up;i++) //注意这里,如果是第一位就不能填0,要从1填起 ans+=dfs(pos-1,i,pre, have8||(i==8),have4||(i==4), have||((i==pre)&&(i==ppre)), limit&&(i==up)); if(!limit) dp[pos][pre][ppre][have8][have4][have]=ans; return ans; } ll sum(ll x) { if(x<1e10||x>=1e11) return 0; memset(c,0,sizeof(c));len=0; while(x) { c[++len]=x%10; x/=10; } memset(dp,-1,sizeof(dp)); return dfs(len,-1,-1,0,0,0,1); } int main() { l=read();r=read(); if(l>r) { printf("0\n"); return 0; } printf("%lld\n",sum(r)-sum(l-1)); return 0; }