AtCoder Beginner Contest 194 F - Digits Paradise in Hexadecimal

本文针对AtCoder上的一道数位DP题目进行详细解析,介绍如何通过状态压缩减少内存使用,并给出具体实现代码。该方法避免了存储具体数字,仅记录数字出现次数,从而简化问题。

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

https://atcoder.jp/contests/abc194/tasks/abc194_f

太菜了又碰到不会的数位DP题了

这题的关键是我们并不用在dp数组中存下当前已经用了哪些数字

只要令dp[pos][cnt][up][lead]=dp[枚举到哪一位了][有几个不同的数字][是否顶着上界][前面是否有非零位了]

只要其中pos,up,lead,对了,那么对于不同的st有相同的cnt,他们的答案是一样的,所以具体的st并不需要存到dp里面,只需要存位数就行了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=2e5+10;
const int mod=1e9+7;

int n,k;
int a[maxl];
ll dp[maxl][17][2][2];
char s[maxl];

inline ll dfs(int pos,int st,bool up,bool lead)
{
	int cnt=__builtin_popcount(st);
	if(cnt>k) return 0;
	if(pos>n) return cnt==k && lead;
	ll &ret=dp[pos][cnt][up][lead];
	if(ret!=-1)
		return ret;
	ret=0;
	int r=up?a[pos]:15;
	for(int i=0;i<=r;i++)
		ret=(ret+dfs(pos+1,(!i&&!lead)?st:st|(1<<i),up&&(i==r),lead|i))%mod;
	return ret;
}

int main()
{
	scanf("%s",s+1);scanf("%d",&k);
	n=strlen(s+1);
	for(int i=1;i<=n;i++)
	if(s[i]>='A' && s[i]<='Z')
		a[i]=s[i]-'A'+10;
	else
		a[i]=s[i]-'0';
	memset(dp,-1,sizeof(dp));
	printf("%lld\n",dfs(1,0,1,0));
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值