HDU 不要62 數位DP

這道題目,雖然不是第一道數位dp,但搞了好幾天,思路倒是簡單,主要是再求一個數下有多少滿足要求的判斷太多了,昨天晚上已經過了很多數據,知道還有些判斷有問題,今天早上改 了一下,AC了;

思路:1,先求出 dp[len][0] (代表長度爲len,滿足條件的個數)  ;dp[len][1] (長度爲len,滿足條件,但開頭爲2), dp[len][2] (長度爲len,滿足條件,開頭bu爲2);

2,對每一個數,求出該數下有多少滿足條件;(最難的一步,很容易搞錯,必須仔細在仔細)

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std ;

int dp[8][3] ;
const int N = 1000000 ;

int fun(int x) {
	int sum = 0 ;
	bool flag = false ;
	for(int i = N , len = 6 ; len >= 0 ;  i/= 10 , --len) {
		int f = x/i ;
		if(f == 0) { flag = false ; continue;}
		if(len == 0) {
            sum += f ;
            if(flag && f > 1) --sum ;
            if(f > 3) --sum ;
            break ;
		}
		if(flag) {
            if(f <= 2) sum += f*dp[len][0] ;
            if(f == 2) {--sum ;break ;}
            if(f == 3) sum += (f-1)*dp[len][0] ;
            if(f > 4 && f <= 6) sum += (f-2)*dp[len][0] ;
            if(f == 4) {sum += (f-1)*dp[len][0] - 1 ; break ;}
            if(f > 6) sum += (f-3)*dp[len][0] + dp[len][2] ;
            if(f == 6) flag = true;
            else flag = false ;
		}else  {
		    if(f < 4) sum += dp[len][0]*f ;
		    if(f == 4) {sum += f*dp[len][0] - 1 ; break ;}
		    if(f > 4 && f <= 6) sum += (f-1)*dp[len][0] ;
		    if(f > 6) sum += (f-2)*dp[len][0] + dp[len][2] ;
		    if(f == 6) flag = true ;
		    else flag = false ;
		}
		x%= i ;
	}
	return sum ;
}

int main() {
	dp[1][0] = 9 ;
	dp[1][1] = 1 ;
	dp[1][2] = 8 ;
	for(int i = 2 ; i < 8 ; ++i) {
		dp[i][1] = dp[i-1][0] ;
		dp[i][2] = dp[i-1][1]*7 + dp[i-1][2]*8 ;
		dp[i][0] = dp[i][1] + dp[i][2] ;
	}
	int a , b ;
	while(scanf("%d%d",&a ,&b )== 2 && a + b) {
	    int s1 = fun(a-1) ;
		int s2 = fun(b) ;
		printf("%d\n" ,s2 - s1);
	}
}

再貼一個看了大牛的博客後寫代碼

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std ;

int dp[8][3] ;
/*
 * dp[i][0] 不含有62和4的個數
 * dp[i][1] 不含有62和4,以2開頭
 * dp[i][2] 含有62或4
 */

void init() {
    dp[0][0] = 1 ;
	dp[1][0] = 9 ; dp[1][1] = 1 ; dp[1][2] = 1 ;
	for(int i = 2 ; i < 8 ; ++i) {
		dp[i][0] = dp[i-1][0]*9 - dp[i-1][1] ;
		dp[i][1] = dp[i-1][0] ;
		dp[i][2] = dp[i-1][2]*10 + dp[i-1][0] + dp[i-1][1] ;
	}
}

int process(int x) {
	int len = 0 ;
	int tmp = x ;
	int bit[9] ;
	while(x) {
		bit[++len] = x%10 ;
		x /= 10 ;
	}
	bit[len+1] = 0 ;
	bool flag = false ;
	int sum = 0 ;
	for(int i = len ; i > 0 ; --i) {
		sum += bit[i]*dp[i-1][2] ;
		if(flag) sum += bit[i]*dp[i-1][0] ;
		else {
			if(bit[i] > 6) sum += dp[i-1][1] ;
			if(bit[i] > 4) sum += dp[i-1][0] ;
			if(bit[i+1] == 6 && bit[i] > 2) {
				sum += dp[i][1] ;
			}
		}
		if(bit[i+1] == 6 && bit[i] == 2 || bit[i] == 4) flag = true ;
	}
	if(flag) ++sum ;
	return tmp - sum ;
}


int main() {
	init() ;
	int n , m ;
	while(scanf("%d%d",&n ,&m)==2 && n + m) {
		printf("%d\n" , process(m) - process(n-1)) ;
	}
}



發佈了48 篇原創文章 · 獲贊 5 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章