hdu2089 不要62

        题意:给一个区间,求区间内满足一定条件的数的个数。条件是,这个数不含4且不含连续的62。

        思路:传说中的数位dp,dp数组打好了,统计那一部分调了好久才弄对,思路不清晰啊。。dp(i,j)表示i位的数,最大位为j,符合这种情况的数中有多少个符合条件。统计时,对每一位从0统计到该位-1。

        比如345就是dp(3,0)+dp(3,1)+dp(3,2)+3打头的小于345的三位数中满足条件的数,因此不能再加上dp(3,3),必须交给dp(2,x)来处理,全部列出来是dp(3,0)+dp(3,1)+dp(3,2)+dp(2,0)+dp(2,1)+dp(2,2)+dp(2,3)+dp(1,0)+dp(1,1)+dp(1,2)+dp(1,3)+dp(1,4),具体见代码。


#include <iostream>    
#include <stdio.h>    
#include <cmath>    
#include <algorithm>    
#include <iomanip>    
#include <cstdlib>    
#include <string>    
#include <memory.h>    
#include <vector>    
#include <queue>    
#include <stack>    
#include <map>  
#include <set>  
#include <ctype.h>    
#include <sstream>
#define INF 1000000
#define ull unsigned long long
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define MAXN 100010

using namespace std;  

int dp[10][10];

int main() {
	dp[0][0]=1;
	for(int i=1;i<8;i++){
		for(int j=0;j<10;j++){
			if(j==4){
				dp[i][j]=0;
				continue;
			}
			for(int k=0;k<10;k++){
				if(!(j==6&&k==2))
					dp[i][j]+=dp[i-1][k];
			}
		}
	}
	
	int l,r;
	while(cin>>l>>r){
		if(l==0&&r==0)break;
		r++;//统计的是小于r的数,所以-1 
		string lstr,rstr;
		stringstream ss,ss2;
		ss<<l;
		ss>>lstr;
		ss2<<r;
		ss2>>rstr;
		
		int lcnt=0;
		int rcnt=0;
		for(int i=0;i<lstr.size();i++){
			//只统计0~对应位-1 
			for(int j=0;j<lstr[i]-48;j++){
				if(i!=0&&(lstr[i-1]=='6'&&j==2) )continue;
				lcnt+=dp[lstr.size()-i][j];
			}
			//如果已经出现了不满足的情况,就不用往下统计了 
			if(lstr[i]=='4'||i>0&&(lstr[i-1]=='6'&&lstr[i]=='2') )break;
		}
		
		for(int i=0;i<rstr.size();i++){
			for(int j=0;j<rstr[i]-48;j++){
				if(i!=0&&(rstr[i-1]=='6'&&j==2) )continue;
				rcnt+=dp[rstr.size()-i][j];
			}
			if(rstr[i]=='4'||i>0&&(rstr[i-1]=='6'&&rstr[i]=='2') )break;
		}
		
		cout<<rcnt-lcnt<<endl;
	}
	return 0;
}



你可能感兴趣的:(HDU,数位dp)