HDU 2089 不要62(数位DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089

题意

求一个区间内,不出现4和连续的62的数的个数。

分析

可以暴力打表。也可以数位DP。

设:

dp[i][0],表示长度为i,不存在不吉利数字
dp[i][1],表示长度为i,不存在不吉利数字,且最高位为2
dp[i][2],表示长度为i,存在不吉利数字

状态定义好了,转移比较简单。

在计算时,按位分解,考虑当前位能否放4或6,详情看代码。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<bitset>
#include<map>
#include<deque>
#include<stack>
using namespace std;
typedef pair<int,int> pii;
#define X first
#define Y second
#define pb push_back
#define mp make_pair
typedef long long ll;
#define ms(a,b) memset(a,b,sizeof(a))
const int inf = 0x3f3f3f3f;
const int maxn = 1e6;
const int mod = 1e9+7;

#define lson l,m,2*rt
#define rson m+1,r,2*rt+1
int dp[10][3];

void init(){
    dp[0][0]=1;
    dp[0][1]=dp[0][2]=0;
    for(int i=1;i<7;i++){
        dp[i][0]=9*dp[i-1][0]-dp[i-1][1]; //在最高位加上除4以外的9个数字,但要减掉2之前加上6
        dp[i][1]=dp[i-1][0]; //在不含不吉利数字的最高位加上2
        dp[i][2]=dp[i-1][0]+dp[i-1][1]+10*dp[i-1][2];
     //在已有不吉利数字前加任意数字,或者无不吉利数字的最高位加4,或者在2前面加6 } }
int bit[10]; int solve(int x){ int t=x; int len=0; while(t){ bit[++len]=t%10; t/=10; } bit[len+1]=0; int ans=0; bool flag=false; for(int i=len;i>=1;i--){ ans += dp[i-1][2]*bit[i]; if(flag) ans+=dp[i-1][0]*bit[i]; //高位已经出现4或者62,后面随意 else{ if(bit[i]>4) ans+=dp[i-1][0]; if(bit[i+1]==6&&bit[i]>2) ans+=dp[i][1]; if(bit[i]>6) ans+=dp[i-1][1]; } if(bit[i]==4 || (bit[i+1]==6&&bit[i]==2)) flag=true; } if(flag) ans++; return x-ans; } int main(){ #ifdef LOCAL freopen("in.txt","r",stdin); #endif // LOCAL int l,r; init(); while(scanf("%d%d",&l,&r)&&(l||r)){ printf("%d\n",solve(r)-solve(l-1)); } return 0; }

以下是暴力打表的代码

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#include<bitset>
#include<map>
#include<deque>
#include<stack>
using namespace std;
typedef pair<int,int> pii;
#define X first
#define Y second
#define pb push_back
#define mp make_pair
typedef long long ll;
#define ms(a,b) memset(a,b,sizeof(a))
const int inf = 0x3f3f3f3f;
const int maxn = 1e6;
const int mod = 1e9+7;

#define lson l,m,2*rt
#define rson m+1,r,2*rt+1
int dp[maxn+5];

void init(){
    dp[0]=0;
    for(int i=1;i<maxn;i++){
        dp[i]=dp[i-1];
        bool f=0;
        int pre=0;
        int x=i;
        while(x){
            if(x%10==4){
                f=1;
                break;
            }else if(pre==2&&x%10==6){
                f=1;
                break;
            }
            pre=x%10;
            x/=10;
        }
        if(f){
            dp[i]++;
        }
    }
}


int main(){
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif // LOCAL
    int l,r;
    init();
    while(scanf("%d%d",&l,&r)&&(l||r)){
        printf("%d\n",r-l+1-(dp[r]-dp[l-1]));
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fht-litost/p/8969961.html