FZU2109 数位dp 含前导零

本文分享了一道关于数位动态规划(DP)的题目解析,特别强调了处理前导0的重要性,并通过实例代码详细说明了如何避免常见的陷阱。文章还提供了AC代码和解题思路,对于理解数位DP及前导0处理技巧非常有帮助。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这题没考虑到前导0,就是不知道哪wa了,又补题一直wa,scanf和printf改成cin cout就对了 真不知道错在哪了。。。刚刚又试了一下,G++scanf过不了 但是visual C++可以。真服了,浪费我又一个多小时。
这道题是简单的数位dp!!!注意前导0!前导0!前导0!掉坑的地方说三遍,顺便庆祝下因为前导0,成功爆0。
思路:就是数位dp模板题,不过置前导0的时候要注意技巧,就是num要放9。为什么放9呢?因为放9不会限制后面取数。暂且这么记吧,我真没整明白为啥放9呜呜呜。
下面是AC代码!一定要掌握前导0的处理!

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define maxn 20
using namespace std;//这题注意前导0!!! 
int dig[maxn];
ll dp[maxn][maxn][2];

ll dfs(int pos,int num,int odd,int pre0,int limit){
	if(!pos) return 1;
	if(!limit&&dp[pos][num][odd]!=-1) return dp[pos][num][odd];
	int up=limit?dig[pos]:9;
	ll ans=0;
	for(int i=0;i<=up;i++){
		if(pre0==0&&i==0) ans+=dfs(pos-1,9,0,0,limit&&i==up);
		else {
			if(!odd&&i<=num) ans+=dfs(pos-1,i,!odd,pre0||i,limit&&i==up); 
			else if(odd&&i>=num) ans+=dfs(pos-1,i,!odd,pre0||i,limit&&i==up);
		}
	}
	if(!limit) dp[pos][num][odd]=ans;
	return ans;
}
ll solve(ll n){
	int pos=0;
	while(n){
		dig[++pos]=n%10;
		n/=10;
	}
	return dfs(pos,9,0,0,1);
}
int main(){
	int T;
	cin>>T;
	memset(dp,-1,sizeof(dp));
	while(T--){
		ll l,r;
		cin>>l>>r;
		cout<<solve(r)-solve(l-1)<<endl;
	}
	return 0;
}

One integer number x is called “Mountain Number” if:

(1) x>0 and x is an integer;

(2) Assume x=a[0]a[1]…a[len-2]a[len-1](0≤a[i]≤9, a[0] is positive). Any a[2i+1] is larger or equal to a[2i] and a[2i+2](if exists).

For example, 111, 132, 893, 7 are “Mountain Number” while 123, 10, 76889 are not “Mountain Number”.

Now you are given L and R, how many “Mountain Number” can be found between L and R (inclusive) ?

Input
The first line of the input contains an integer T (T≤100), indicating the number of test cases.

Then T cases, for any case, only two integers L and R (1≤L≤R≤1,000,000,000).

Output
For each test case, output the number of “Mountain Number” between L and R in a single line.
Sample Input
3
1 10
1 100
1 1000
Sample Output
9
54
384

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值