[SGU390]Tickets && 数位DP

这是一篇关于解决数论问题的博客,详细介绍了如何运用一棵十叉树来统计各个数位之和,并利用动态规划(DP)解决SGU390题目中的复杂情况。博客中提到,由于数位可能不完整地分成若干组,所以需要记录每个数位的和(sum)以及剩余空间(rem)。在DP过程中,作者强调了同时跟踪组数和剩余空间的重要性,以及如何通过unlimit1和unlimit2参数来处理数值范围限制的情况。

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

超级难想的一道题


用一棵十叉数来统计 

因为是各个数位之和 所以要把之前各个数位的和sum记录下来 

因为每个数位(子树)并不一定完整的分成cnt组 最后可能有剩余 所以每一个数位(子树)前面肯能会有多余的空间 用rem记录

因为需要每组末的空间是在统计时不断改变的 所以dp时要同时记录组数和最后的空余


实现方面 沿用上一个记忆化搜索的思路 传入两个参数unlimit1 unlimit2 表示该位置上的数的取值是否受到读入的L 和 R 的限制 只有不受限制时找到的DP值才能作为d数组中的元素记录下来


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int MAXN = 18;
const int MAXK = 1000;
struct node{
	LL cnt, res;
	node(){}
	node(LL x, LL y) { cnt = x; res = y; }
	node operator += (node t)
	{
		cnt += t.cnt;
		res = t.res;
		return *this;
	}
}d[MAXN+10][MAXN * 9 + 10][MAXK+10];
bool vis[MAXN+10][MAXN * 9 + 10][MAXK+10];
int digL[MAXN+10], digR[MAXN+10];
LL L, R, K;
node dp(int h, int sum, int rem, bool unlimit1, bool unlimit2)
{
	if(h == 0) {
		if(sum + rem >= K) return node(1, 0);
		return node(0, sum + rem);
	}
	if(vis[h][sum][rem] && unlimit1 && unlimit2) return d[h][sum][rem];
	node ans(0, rem);
	int st = !unlimit1 ? digL[h] : 0;
	int ed = !unlimit2 ? digR[h] : 9;
	for(int i = st; i <= ed; i++)
		ans += dp(h-1, sum + i, ans.res, (unlimit1 || i > digL[h]), (unlimit2 || i < digR[h]));
	if(unlimit1 && unlimit2) {
		d[h][sum][rem] = ans;
		vis[h][sum][rem] = true;
	}
	return ans;
}
int main()
{
	cin >> L >> R >> K;
	while(L) {
		digL[++digL[0]] = L % 10;
		L /= 10;
	}
	while(R) {
		digR[++digR[0]] = R % 10;
		R /= 10;
	}
	node ans = dp(digR[0], 0, 0, 0, 0);
	cout << ans.cnt;


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值