bzoj4521 [Cqoi2016]手机号码(数位dp)

大概就是个奇怪的dp。
嗯,自己乱搞了很久失败了gg
orzVisjiao题解吧:portal
累觉不爱.jpg

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline ll read(){
    ll x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
ll f[13][10][2][2][4][2];//s1--是否已有三连,s2--i与i-1是否相同,s3--4,8情况,s4--前i位是否达到上限 
int a[13];
struct Icefox{
    int i,x,s1,s2,s3,s4;
    Icefox(int _i,int _x,int _s1,int _s2,int _s3,int _s4){i=_i;x=_x;s1=_s1;s2=_s2;s3=_s3;s4=_s4;}
};
inline int is48(int x){return (x==8)<<1|(x==4);}
inline ll solve(ll n){
    for(int i=11;i>=1;--i) a[i]=n%10,n/=10;
    queue<Icefox>q;ll ans=0;memset(f,0,sizeof(f));
    for(int x=1;x<=a[1];++x){
        int s1=0,s2=0,s3=is48(x),s4=(x==a[1]);
        f[1][x][s1][s2][s3][s4]=1;
        q.push(Icefox(1,x,s1,s2,s3,s4));
    }while(!q.empty()){
        Icefox b=q.front();q.pop();
        int i=b.i+1,mx=b.s4?a[i]:9,val=f[b.i][b.x][b.s1][b.s2][b.s3][b.s4];
        for(int x=0;x<=mx;++x){
            int s2=(x==b.x),s1=b.s1|(b.s2&s2),s3=b.s3|is48(x),s4=b.s4&(x==a[i]);
            if(i<11&&!f[i][x][s1][s2][s3][s4]) q.push(Icefox(i,x,s1,s2,s3,s4));
            f[i][x][s1][s2][s3][s4]+=val;
        }
    }for(int s2=0;s2<2;++s2)
        for(int s3=0;s3<3;++s3)
            for(int s4=0;s4<2;++s4)
                for(int x=0;x<=9;++x)
                    ans+=f[11][x][1][s2][s3][s4];
    return ans;
}
int main(){
//  freopen("a.in","r",stdin);
    ll l=read(),r=read();
    if(l==1e10) printf("%lld\n",solve(r));
    else printf("%lld\n",solve(r)-solve(l-1));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/icefox_zhx/article/details/80490096