acdream 1064 完美数 (数位dp)

题意:

求出区间中要么含3要么含8的数的个数。

题解:

直接搞设dp[pos][ha][hb][num],num=0表示含3,num=1表示含8,ha表示是否包含num,hb则相反。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const ll OO=0x3f3f3f3f3f3f3f3f;
const ll MOD=1000000007;
const int maxn = 50000;
int dp[30][2][2][2],bit[30];
int num,a,b;

int dfs(int pos,int ha,int hb,int f){
    if(pos<0) return (ha&&!hb);
    if(!f&&dp[pos][ha][hb][num]!=-1)
        return dp[pos][ha][hb][num];
    int last = f ? bit[pos] : 9;
    int res=0;
    for(int i=0;i<=last;i++){
        res+=dfs(pos-1,ha||i==a,hb||i==b,f&&i==last);
    }
    if(!f) dp[pos][ha][hb][num]=res;
    return res;
}

int Count(int n){
    int len=0;
    while(n){
        bit[len++]=n%10;
        n/=10;
    }
    a=3;b=8;num=0;
    int ans1=dfs(len-1,0,0,1);
    a=8;b=3;num=1;
    int ans2=dfs(len-1,0,0,1);
    return ans1+ans2;
}

int main(){
    //freopen("E:\\read.txt","r",stdin);
    int T,L,R;
    scanf("%d",&T);
    memset(dp,-1,sizeof dp);
    while(T--){
        scanf("%d %d",&L,&R);
        printf("%d\n",Count(R)-Count(L-1));
    }
    return 0;
}





你可能感兴趣的:(acdream 1064 完美数 (数位dp))