BZOJ 4521: [Cqoi2016]手机号码

来源:互联网 发布:烟台淘宝运营 编辑:程序博客网 时间:2024/05/18 18:21

比较好搞(暴力)的数位DP

f[pos][a][b][c1][c2][c3][flag]

表示目前决策第pos位,a是pos+2位,b是pos+1位,c1表示是否有3个连续的,c2表示是否有4,c3表示是否有8,flag表示这一位能不能取比原数大的

#include<cstdio>#include<iostream>#include<cstring>#include<cmath>#include<queue>#include<vector>#include<algorithm>#include<map>#include<set>#define rep(i,l,r) for(int i=l;i<=r;i++)#define per(i,r,l) for(int i=r;i>=l;i--)#define mmt(a,v) memset(a,v,sizeof(a))#define tra(i,u) for(int i=head[u];i;i=e[i].next)using namespace std;typedef long long ll;ll f[15][10][10][2][2][2][2];bool vis[15][10][10][2][2][2][2];int dpt[15];ll dp(int pos,int a,int b,bool c1,bool c2,bool c3,bool flag){if(vis[pos][a][b][c1][c2][c3][flag])return f[pos][a][b][c1][c2][c3][flag];vis[pos][a][b][c1][c2][c3][flag]=1;ll &ans=f[pos][a][b][c1][c2][c3][flag];if(c2&&c3)return ans=0;if(!pos)return ans=c1;int l=(pos==11)?1:0,r=flag?9:dpt[pos];rep(i,l,r)ans+=dp(pos-1,b,i,c1||(a==b&&b==i),c2||(i==4),c3||(i==8),flag||(i<dpt[pos]));return ans;}ll calc(ll x){dpt[0]=0;while(x)dpt[++dpt[0]]=x%10,x/=10;mmt(f,0);mmt(vis,0);dp(11,0,0,0,0,0,0);return f[11][0][0][0][0][0][0];}int main(){//freopen("a.in","r",stdin);ll l,r;scanf("%lld %lld\n",&l,&r);if(l==(ll)1e10)printf("%lld\n",calc(r));else printf("%lld\n",calc(r)-calc(l-1));return 0;}


0 0