Harmony Pairs 2020牛客暑期多校训练营(第六场)

本文介绍了一种使用数位动态规划(DP)解决数论中特定问题的方法,通过枚举大小关系和差值,简化了原本复杂的分情况讨论策略。文章详细展示了如何在限定条件下,递归地构建解决方案,最终实现对S(B)-S(A)+1000<1000的方案数的高效计算。

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

https://ac.nowcoder.com/acm/contest/5671/H

第一版只有我们队没过H。。。。

我们只会分情况讨论,a的位数小于b的位数的时候求个方案数,a的位数等于b的位数的时候数位dp求方案数,队友调了快一个多小时,赛后过了。。。

然而直接在一个dfs里面枚举b<=n和a<=b的大小关系,然后枚举差值,巨简单。。

f[k][sum][fb][fa]表示现在枚举到第k位,S(B)-S(A)+1000=sum,fb==1为前k位于n相等,0为已经<n,fa==1表示前k位A=B,0为A<B,此时最后能S(B)-S(A)+1000<1000的方案数

然后根据枚举第k位A和B分别放哪个数,根据fb,fa设个上限,让B<=N和A<=B始终成立就行了

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

const int maxl=102;
const int mid=1000;
const int mod=1e9+7;
int n;
int a[maxl];
ll dp[maxl][mid*2][2][2];
char s[maxl];

inline void prework()
{
	scanf("%s",s+1);
	n=strlen(s+1);
	for(int i=1;i<=n;i++)
		a[i]=s[i]-'0';
}

inline ll dfs(int k,int sum,bool fb,bool fa)
{
	if(k>n)
		return (ll)(sum<mid); 
	if(dp[k][sum][fb][fa]!=-1)
		return dp[k][sum][fb][fa];
	ll ret=0;
	for(int i=0;i<=(fb?a[k]:9);i++)
		for(int j=0;j<=(fa?i:9);j++)
			ret=(ret+dfs(k+1,sum+i-j,fb&&(i==a[k]),fa&&(j==i)))%mod;
	dp[k][sum][fb][fa]=ret;
	return ret;
}

inline void mainwork()
{
	memset(dp,-1,sizeof(dp));
	printf("%lld\n",dfs(1,mid,1,1));
}

int main()
{
	prework();
	mainwork();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值