【翻译】F - Max Sum Counting Editorial by en_translator

本文介绍如何用动态规划求解序列A和B的排序问题,涉及子集和计算,时间复杂度为O(Nmax(A))。
摘要由CSDN通过智能技术生成

给定两个序列 A 和 B,按照 A_i 的增序对它们进行排序(如果 A_i 相等,则按照 B_i 来确定顺序)。对于集合 {1, 2, ..., N} 的每个非空子集 S,满足 max_{i∈S} A_i = A_{max(S)}。因此,我们可以将问题转化如下。

定义 f(i, j) 为从 B_1, B_2, ..., B_i 中选择零个或多个元素,使它们的和等于 j。求下面的值:

∑ {i=1} ^ {N}   ∑ {j=0} ^ {A_i - B_i}   f(i-1, j)

显然,对于 f(i, j),我们只需考虑 i 在 0 到 N(包括两端)之间的取值范围,以及 j 在 0 到 max(A)(包括两端)之间的取值范围。因此,我们可以适当使用动态规划(DP)来计算 f(i, j) 的值,从而在总共 O(Nmax(A)) 的时间复杂度内解决问题。

#include<bits/stdc++.h>
using namespace std;
const int mod = 998244353, maxi = 5000;
int main(){
	int N; cin >> N;
	vector<pair<int,int>> data(N);
	for(int i=0; i<N; i++) cin >> data[i].first;
	for(int i=0; i<N; i++) cin >> data[i].second;
	sort(data.begin(),data.end());
	vector<int> A(N),B(N);
	for(int i=0; i<N; i++) tie(A[i],B[i]) = data[i];
	vector<vector<int>> dp(N+1,vector<int>(maxi+1));
	dp[0][0] = 1;
	int ans = 0;
	for(int i=0; i<N; i++){
		for(int j=0; j<=maxi; j++){
			dp[i+1][j] = dp[i][j];
			if(B[i] <= j){
				dp[i+1][j] += dp[i][j-B[i]];
				dp[i+1][j] %= mod;
			}
			if(j <= A[i]-B[i]){
				ans += dp[i][j];
				ans %= mod;
			}
		}
	}
	cout << ans << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值