HDU 2089 不要62 数位DP

本文介绍了一种计算指定范围内不包含特定数字(如4和62)的有效方法。通过两种不同的算法实现:一种是基于深度优先搜索(DFS)的数位DP模板,另一种则是通过找出不满足条件的数字并从中减去的方法。这两种方法都能有效地解决该问题。

题目:给定范围,求这个范围内不含有4 和 62 的数字有多少个。

两种方法

第一种方法是dfs搜索,顺便记忆化一下,也是数位dp的模板

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring> 

using namespace std; 

int line[10]; 
int dp[10][2]; 
int dfs( int len, int pre,int flag )
{
	if ( len==0 ) return 1; // 因为搜索的入口是满足条件的,所以return  1 
	if ( !flag && dp[len][pre]!=-1 ) return dp[len][pre];
	int end = flag?line[len]:9; 
	int ans = 0; 
	for ( int i=0;i<=end;i++ ) 
	{
		if ( i!=4 && !( pre&&i==2) ) ans += dfs( len-1,i==6,flag&&i==end ); 
	}
	if ( !flag ) dp[len][pre] = ans; 
	return ans; 
}
int solve( int x )
{
	int t = x; 
	int len = 0; 
	while( t )
	{
		line[++len] = t%10; 
		t /= 10 ; 
	}
	memset( dp,-1,sizeof dp ); 
	return dfs( len ,0 ,1 ) ; 
}


int main()
{
	int r,l; 
	
	while( scanf("%d%d",&l,&r) )
	{
		if ( l==0 && r==0 ) break; 
		cout<<solve( r ) - solve( l-1 ) <<endl; 
	}
	return 0; 
}





找出来不吉利的数字,然后减掉,但是不会判断x是否满足条件

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

int dp[10][3];
int a[10]; 
void init()
{
	dp[0][0] = 1 ; 
	for ( int i=1; i<=8; i++ ) 
	{
		
		dp[i][0] = dp[i-1][0]*9 - dp[i-1][1] ;   //i位不满足条件的
		dp[i][1] = dp[i-1][0] ; //i位 不满足条件中 最高位是2 的
		dp[i][2] = dp[i-1][0] + dp[i-1][1] + dp[i-1][2]*10; // 满足条件
	}
} 
int solve ( int x )
{
	int cnt = 0 ;
	int temp = x ,len =0 ; 
	while ( temp ) 
	{
		a[++len] = temp%10; 
		temp /=10; 
	}
	a[ len+1 ] = 0 ; 
	int flag = 0 ;
	for ( int i=len; i>=1; i-- ) 
	{
		cnt += a[i]*dp[i-1][2]; 
		if ( flag ) {
			cnt += dp[i-1][0]*a[i]; 
		}
		else {
			if ( a[i]>4 ) cnt+=dp[i-1][0];
			if ( a[i]>2 && a[i+1]==6 ) cnt+=dp[i][1]; 
			if ( a[i]>6 ) cnt+=dp[i-1][1]; //!!
			if ( a[i]==4 ||( a[i]==2 && a[i+1]==6 ) ) flag = 1; 
		}
	}
	return x-cnt ; 
}
int main()
{	
	int n,m; 
	init(); 
	while( scanf("%d%d",&m,&n) )
	{
		if ( m==0 && m==n ) break; 
		printf("%d\n",solve( n+1 ) - solve( m ) )	; 
	}  
	return 0; 
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值