【BZOJ4521】【CQOI2016】手机号码 数位DP

来源:互联网 发布:1050ti 知乎 编辑:程序博客网 时间:2024/04/29 02:04

所以说CQOI板子背少了没人权。。。Day1唯一A了的题目

题目非常良心的帮人们略去了前导零的烦恼,给定的范围一定是十一位的整数,但这同时意味着裸对拍真!的!好!慢!

设状态DP(i,j,k,ok1,ok2)表示前i位最后一位是j倒数第二位是k,ok1记录是否已经有三连续,ok2记录4和8出现的情况(不能同时出现所以可以压到一位),再加上一堆奇奇怪怪的细节,递推思路倒是比较清晰。

注意如果他上界给的99999999999(差不多就是这么多个)我们计算时一进位就会出事。。。记得特判一下(我也不知道有没有这种数据)

#include<cstdlib>#include<cstdio>#include<iostream>#include<cstring>#include<cmath>#include<algorithm>#include<queue>#include<vector>using namespace std;long long L,R;int a[15],ct;long long dp[15][15][15][5][5];void ready(){memset(dp,0,sizeof(dp));dp[0][0][0][0][0]=1;for(int i=0;i<11;i++)//少年你怕了吗{for(int j=0;j<=9;j++){for(int k=0;k<=9;k++){for(int u=0;u<=1;u++){for(int v=0;v<=2;v++)if(dp[i][j][k][u][v]){for(int w=0;w<=9;w++){if(v==1 && w==8)continue;if(v==2 && w==4)continue;if(i>=2 && w==j && j==k){if(w==4){dp[i+1][w][j][1][1]+=dp[i][j][k][u][v];}else if(w==8){dp[i+1][w][j][1][2]+=dp[i][j][k][u][v];}else{dp[i+1][w][j][1][v]+=dp[i][j][k][u][v];}}else{if(w==4){dp[i+1][w][j][u][1]+=dp[i][j][k][u][v];}else if(w==8){dp[i+1][w][j][u][2]+=dp[i][j][k][u][v];}else{dp[i+1][w][j][u][v]+=dp[i][j][k][u][v];}}}}}}}}return ;}long long f(long long x){ct=0; while(x){a[++ct]=x%10; x=x/10;}if(ct==10)return 0;long long ans=0;int c=0,w=0;if(ct==12){for(int i=1;i<=9;i++){for(int j=0;j<=9;j++){ans+=dp[11][i][j][1][0];ans+=dp[11][i][j][1][1];ans+=dp[11][i][j][1][2];}}return ans;}for(int i=ct;i>=1;i--){if(i==ct){for(int j=1;j<a[i];j++){for(int k=0;k<=9;k++){ans+=dp[i][j][k][1][0];ans+=dp[i][j][k][1][1];ans+=dp[i][j][k][1][2];}}}else{if(w==1){for(int j=0;j<a[i];j++){if(c==1 && j==8)continue;if(c==2 && j==4)continue;for(int k=0;k<=9;k++){if(c==1 && k==8)continue;if(c==2 && k==4)continue;ans+=dp[i][j][k][0][0];if(c!=2)ans+=dp[i][j][k][0][1];if(c!=1)ans+=dp[i][j][k][0][2];ans+=dp[i][j][k][1][0];if(c!=2)ans+=dp[i][j][k][1][1];if(c!=1)ans+=dp[i][j][k][1][2];}}}else if(i<=ct-2 && a[i+2]==a[i+1]){for(int j=0;j<a[i];j++){if(c==1 && j==8)continue;if(c==2 && j==4)continue;if(j==a[i+1]){for(int k=0;k<=9;k++){if(c==1 && k==8)continue;if(c==2 && k==4)continue;ans+=dp[i][j][k][0][0];if(c!=2)ans+=dp[i][j][k][0][1];if(c!=1)ans+=dp[i][j][k][0][2];ans+=dp[i][j][k][1][0];if(c!=2)ans+=dp[i][j][k][1][1];if(c!=1)ans+=dp[i][j][k][1][2];}}else{for(int k=0;k<=9;k++){if(c==1 && k==8)continue;if(c==2 && k==4)continue;ans+=dp[i][j][k][1][0];if(c!=2)ans+=dp[i][j][k][1][1];if(c!=1)ans+=dp[i][j][k][1][2];}}}}else{for(int j=0;j<a[i];j++){if(c==1 && j==8)continue;if(c==2 && j==4)continue;if(j==a[i+1] && i>=2){for(int k=0;k<=9;k++){if(c==1 && k==8)continue;if(c==2 && k==4)continue;if(j==k){ans+=dp[i][j][k][0][0];if(c!=2)ans+=dp[i][j][k][0][1];if(c!=1)ans+=dp[i][j][k][0][2];ans+=dp[i][j][k][1][0];if(c!=2)ans+=dp[i][j][k][1][1];if(c!=1)ans+=dp[i][j][k][1][2];}else{ans+=dp[i][j][k][1][0];if(c!=2)ans+=dp[i][j][k][1][1];if(c!=1)ans+=dp[i][j][k][1][2];}}}else{for(int k=0;k<=9;k++){if(c==1 && k==8)continue;if(c==2 && k==4)continue;ans+=dp[i][j][k][1][0];if(c!=2)ans+=dp[i][j][k][1][1];if(c!=1)ans+=dp[i][j][k][1][2];}}}}}if(a[i]==4){if(c==2)break;c=1;}else if(a[i]==8){if(c==1)break;c=2;}if(i<=ct-2 && a[i]==a[i+1] && a[i+1]==a[i+2]){w=1;}//cout<<ans<<endl;}return ans;}int main(){//freopen("number.in","r",stdin);//freopen("number.out","w",stdout);cin>>L>>R;ready();cout<<f(R+1)-f(L)<<endl;return 0;}


0 0
原创粉丝点击