HDU 5898 odd-even number(数位dp)

套路题,维护前面的奇偶性和长度

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int N=1e5+10;
int s[N];
ll f[30][2][2][4][4];
int len;
ll dfs(int u,int sign,int g,int num,int flag){
    if(u==len+1){
        if((num%2)&&(flag%2)){
            return 0;
        }
        if((num%2==0)&&(flag%2==0)){
            return 0;
        }
        return 1;
    }
    if(f[u][sign][g][num][flag]!=-1)
        return f[u][sign][g][num][flag];
    int up;
    if(sign)
        up=s[u];
    else
        up=9;
    int i;
    ll res=0;
    auto &x=f[u][sign][g][num][flag];
    for(i=0;i<=up;i++){
        if(g&&(i==0)){
            res+=dfs(u+1,sign&&(i==up),g,1,0);
            continue;
        }
        if((num%2==0)&&(i%2==0)){
            res+=dfs(u+1,sign&&(i==up),0,0,!flag);
        }
        if((num%2==0)&&(i%2)){
            if(flag){
                res+=dfs(u+1,sign&&(i==up),0,1,1);
            }
        }
        if((num%2)&&(i%2==0)){
            if(flag%2==0){
                res+=dfs(u+1,sign&&(i==up),0,0,1);
            }
        }
        if((num%2)&&(i%2)){
            res+=dfs(u+1,sign&&(i==up),0,1,!flag);
        }
    }
    return x=res;
}
ll get(ll x){
    if(x==0)
        return 1;
    int cnt=0;
    while(x){
        s[cnt++]=x%10;
        x/=10;
    }
    memset(f,-1,sizeof f);
    len=cnt-1;
    reverse(s,s+cnt);
    return dfs(0,1,1,1,0);
}
int main(){
    ios::sync_with_stdio(false);
    int t;
    cin>>t;
    int cnt=0;
    while(t--){
        ll l,r;
        cin>>l>>r;
        cout<<"Case #"<<++cnt<<": ";
        cout<<get(r)-get(l-1)<<endl;
    }
    return 0;
}
View Code

 

posted @ 2020-12-10 19:46  朝暮不思  阅读(61)  评论(0)    收藏  举报