2023牛客多校第五场 - D G H

比赛地址:传送门
赛时过了 3 题,后期坐大牢!
G 尺取法双指针
H 动态规划,背包DP

D Cirno's Perfect Equation Class

题意
给定 \(k, c, n\),求正数对 \((a,b)\) 的个数满足 $ka + b = c, b | c (c = bx, x \ge 1), gcd(a,b) \ge n $

思路
不难发现 b 是 c 的因子,所以枚举 b,判断相应的 a 是否满足条件即可

代码

void solve(){
	int k, c, n;
	cin >> k >> c >> n;
	vector<int> s;
	for(int i = 1; i * i <= c; ++ i){
		if(c % i == 0){
			s.push_back(i);
			if(i * i != c) s.push_back(c / i);
		}
	}
	sort(s.begin(), s.end());
	int ans = 0;
	for(auto b : s){
		int a = (c - b) / k;
		if(a * k == c - b && a > 0 && __gcd(a, b) >= n) ++ ans;
	}
	cout << ans << '\n';
	return ;
}

G Go to Play Maimai DX

题意
给定长为 n 的数组和数 k ,数组中每个数均$\in [1, 4] $,需要找到最小的区间,包含至少一个数字 1,2,3,包含 k 个 4。

思路
尺取法即可

代码

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 1e5 + 5, inf = 0x3f3f3f3f, mod = 998244353;
int n, k, a[maxm], c[5];

void solve(){
	cin >> n >> k;
	for(int i = 0; i < n; ++ i){
		cin >> a[i];
	}
	int l = 0, r = 0, lei = 0, ans = n + 1;
	while(r < n){
		while(lei <= 4 && r < n){
			++ c[a[r]];
			if(c[a[r]] == 1) ++ lei;
			++ r;
			if(c[4] >= k && lei == 4) break;
		}
		-- r;
		if(lei < 4 || c[4] < k) break;
		while(c[a[l]] > 1 && a[l] != 4 || c[a[l]] > k && a[l] == 4){
			-- c[a[l]];
			++ l;
		}
		ans = min(ans, r - l + 1);
		-- c[a[l]];
		if(c[a[l]] == 0) -- lei;
		++ l;
		++ r;
	}
	cout << ans << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int _ = 1;
	// cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}


H Nazrin the Greeeeeedy Mouse

题意
详见题面
There're $ n $ cheeses in the house. The $i-th $ cheese is between point $i $ and point $i + 1 $ . The \(i-th\) cheese's size is \(a_i\) and its weight is $b_i $.
Nazrin is at point $1 $ in the beginning and wants to steal some cheeses. She has $m $ chances to take the cheeses:
In the $i-th $ time, Nazrin brings a bag of size \(sz_i\) . Since she's greedy, for \(i > 1\),$sz_i > sz_{i - 1} $ always holds. She can travel from point \(1\) and take some cheeses. She can only travel from point \(x\) to \(x + 1\), or backwards. If she wants to travel from point \(x\) to point \(x + 1\), she has to dig a hole on the \(x-th\) cheese or take it. She can't take a cheese with a hole on it. Of course, the sum of the cheeses' size she takes in the \(i-th\) time can't be larger than \(sz_i\). After taking the cheeses, she needs to go back to point 1.
Please maximize the sum of the weights of taken cheeses and output it.
$1 \le n \le 200, 1 \le m \le 10^5, 1 \le a_i \le 200, 1 \le b_i \le 10^5, 1\le sz_i \le 200 $

思路
没那么简单的01背包DP,多个01相互牵制背包DP取最优
有个小提示就是当 \(n < m\) 时,我们可以仅用后 n 个背包即可。从前往后遍历物品,对于每一个背包都做背包DP,那么我们就可以获得对于所有背包自己的最大值,之后我们再进行一步操作,就是将前一个背包的最大值转移到后一个背包的 0 空间上去,因为最终的最大如果不在单个背包上取,那就在多个背包共同取,而后一个背包取需要在前一个背包的基础上取!
理解的还不是很透彻,详见代码。。。

代码

//>>>Qiansui
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define mem(x,y) memset(x, y, sizeof(x))
#define debug(x) cout << #x << " = " << x << '\n'
#define debug2(x,y) cout << #x << " = " << x << " " << #y << " = "<< y << '\n'
//#define int long long

using namespace std;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> pull;
typedef pair<double, double> pdd;
/*

*/
const int maxm = 2e2 + 5, inf = 0x3f3f3f3f, mod = 998244353;

void solve(){
	int n, m;
	cin >> n >> m;
	vector<int> a(n), b(n), h(m);
	for(int i = 0; i < n; ++ i){
		cin >> a[i] >> b[i];
	}
	for(int c = 0; c < m; ++ c){
		cin >> h[c];
	}
	if(m > n){
		h.erase(h.begin(), h.end() - n);
		m = n;
	}
	vector<vector<int>> dp(m, vector<int>(maxm, 0));
	for(int i = 0; i < n; ++ i){            // i 个物品
		for(int j = 0; j < m; ++ j){        //每个包
			for(int k = h[j]; k >= a[i]; --k){
				dp[j][k] = max(dp[j][k], dp[j][k - a[i]] + b[i]);
			}
		}
		for(int j = 0; j < m - 1; ++ j){    //将前面的最优状态转到下一背包的 0 空间状态
			for(int k = 0; k <= h[j]; ++ k){
				dp[j + 1][0] = max(dp[j + 1][0], dp[j][k]);
			}
		}
	}
	int ans = 0;
	for(int i = 0; i <= h[m - 1]; ++ i){    //最终的答案即为最后一背包的最大值
		ans = max(ans, dp[m - 1][i]);
	}
	cout << ans << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int _ = 1;
	// cin >> _;
	while(_ --){
		solve();
	}
	return 0;
}

posted on 2023-07-31 18:59  Qiansui  阅读(6)  评论(0编辑  收藏  举报