[ABC159F] Knapsack for All Segments题解

题目传送门

题目传送门(洛谷)
题目传送门(atcoder)

Step1 理解题意

  • 给定一个 n n n 和一个 s s s
  • 给定一个长度为 n n n 的正整数数组 a a a
  • 定义函数 f ( L , R ) f(L,R) f(L,R) 是指在 L L L R R R 的区间内能使其中子串(子串是不需要连续的)之和为 s s s 的子串数量
  • 求在 a a a 中所有 f ( L , R ) f(L,R) f(L,R) 之和
  • 结果对 998244353 998244353 998244353 取模
  • 1 ≤ N , S , A i ≤ 3000 1 \leq N,S,A_i \leq 3000 1N,S,Ai3000

Step2 思路解释

d p i , j dp_{i,j} dpi,j指在前 i i i 个数的总和为 j j j,那么我们易得以下转移方程:
d p i , j ← ( d p i − 1 , j + d p i − 1 , j − a i ) m o d    p dp_{ i,j} \gets (dp_{i−1,j}+dp_{ i−1,j−a _i }) \mod p dpi,j(dpi1,j+dpi1,jai)modp

Step3 简化数组

  • 因为每次枚举 d p i , j dp_{ i , j } dpi,j都只要用到 d p i − 1 , x dp_{ i -1 , x} dpi1,x,所以我们可以省去一维,即用 d p i dp_i dpi 表示 d p i , j dp_{i,j} dpi,j
  • 如果只考虑 A i = S A_i = S Ai=S 的情况,则会少算 i i i 种右端点为 i i i 的方案,所以对于每个 i i i,应该使 d p 0 ← i dp_0 \gets i dp0i

Step4 Ac code

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int mod = 998244353;

int a[3005],dp[3005];
int ans;
signed main(){
	int n ,s;
	scanf("%lld%lld",&n,&s);
	for(int i = 1; i <= n; i++) scanf("%lld",&a[i]);
	for(int i = 1; i <= n ;i++){
		dp[0]++;
		for(int j = s; j >= a[i]; j--){
			dp[j] = (dp[j] + dp[j - a[i]]) % mod; 
		}
		ans += dp[s];
		ans %= mod;
	}
	printf("%lld",ans);
	return 0;
}

  • 44
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
The 0-1 Knapsack Problem is a classic optimization problem in computer science and mathematics. The problem is as follows: Given a set of items, each with a weight and a value, determine the items to include in a collection so that the total weight is less than or equal to a given limit and the total value is as large as possible. The 0-1 indicates that each item can only be included once or not at all. This problem can be solved using dynamic programming. We can create a two-dimensional array where the rows represent the items and the columns represent the weight limit. For each item and weight limit, we can calculate the maximum value that can be obtained by either including the item or excluding it. We can then fill in the array row by row until we reach the final row, which represents the optimal solution. Here is an example implementation of the 0-1 Knapsack Problem in Java: ``` public class Knapsack { public static int knapsack(int[] values, int[] weights, int limit) { int[][] dp = new int[values.length + 1][limit + 1]; for (int i = 1; i <= values.length; i++) { for (int j = 1; j <= limit; j++) { if (weights[i-1] > j) { dp[i][j] = dp[i-1][j]; } else { dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weights[i-1]] + values[i-1]); } } } return dp[values.length][limit]; } public static void main(String[] args) { int[] values = {60, 100, 120}; int[] weights = {10, 20, 30}; int limit = 50; int result = knapsack(values, weights, limit); System.out.println("Maximum value: " + result); } } ``` In this example, we have three items with values of 60, 100, and 120 and weights of 10, 20, and 30, respectively. We want to find the maximum value we can obtain with a weight limit of 50. The result is 220, which indicates that we should select items 2 and 3 to maximize the value while staying under the weight limit.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值