【牛客】2024暑期牛客多校3 补题记录

  • 明天应该会补完 E 和 H

A - Bridging the Gap 2(贪心)

  • 计算总共需要的次数,除去最后一次(因为不需要回对岸),前面需要往返的次数是 c n t = ⌈ n − R R − L ⌉ cnt=\lceil \frac{n-R}{R-L}\rceil cnt=RLnR,所以需要多来回的人数是 c n t × L cnt\times L cnt×L
  • 每个人自己过河需要 1 1 1 的体力,那每个人可以多往返的次数就是 h i − 1 2 \frac{h_i-1}{2} 2hi1,这个值需要和 c n t cnt cnt 取最小值(因为一个人在一次往返中最多贡献 1 1 1
  • 可以往返的次数累加起来大于 c n t × L cnt\times L cnt×L 的话就 Y e s Yes Yes,否则 N o No No
#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 1e6 + 10;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
	int n, l, r;
	cin >> n >> l >> r;
	vector<int> a(1);
	int cnt = (n - r) / (r - l);
	if ((n - r) % (r - l) != 0) cnt ++ ;
	for (int i = 0; i < n; i ++ )
	{
		int x; cin >> x;
		if ((x - 1) / 2 > 0) a.push_back(min(cnt, (x - 1) / 2));
	}
	sort(a.begin() + 1, a.end());

	int m = a.size() - 1;
	vector<int> pre(m + 1);
	for (int i = 1; i <= m; i ++ ) pre[i] = pre[i - 1] + a[i];

	if (cnt == 0) cout << "YES\n";
	else
	{
		if (pre[m] < cnt * l) cout << "NO\n";
		else cout << "YES\n";
	}
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t = 1;
	// cin >> t;
	while (t--)
	{
		solve();
	}
}

B - Crash Test(数学)

  • 不知道怎么证明的 队友看了一眼就秒了
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include <iomanip>
#include<random>

using namespace std;
typedef long long LL;
typedef __int128 i128;
typedef unsigned long long ULL;
typedef double db;
#define int long long
const int N = 110;
int n , h[N] , d;

void Asuka()
{
	cin >> n >> d;
	for(int i = 1 ; i <= n ; i ++)
		cin >> h[i];
	int g = h[1];
	for(int i = 2 ; i <= n ; i ++){
		g = __gcd(g , h[i]);
	}
	cout << min(d % g , g - (d % g))<< '\n';
	return;
}	

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);

	int t = 1;
	// cin >> t;
	while(t --){
		Asuka();
	}
	return 0;
}

D - Dominoes!(构造)

  • 首先记录每个数字出现的次数,大于 n − 1 n-1 n1 次就直接 N O NO NO
  • 之后先放 x , y x,y x,y 一样的牌,贪心尽可能放数量多的,总之实现起来有一定难度,但是赛时没有往下想真的太可惜了
#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 1e6 + 10;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
	int n; cin >> n;
	map<int, int> cnt, mp;
	priority_queue<PII> same;
	vector<PII> ed;
	for (int i = 1; i <= n; i ++ )
	{
		int a, b;
		cin >> a >> b;
		if (a == b) mp[a] ++ ;
		else ed.push_back({a, b});
		cnt[a] ++, cnt[b] ++ ;
	}
	for (auto t : cnt)
	{
		if (t.second > n + 1)
		{
			cout << "NO\n";
			return;
		}
	}
	cout << "YES\n";
	for (auto t : mp) same.push({t.second, t.first});
	vector<PII> ans(1);
	int lst = -1;
	auto work = [&](int num, int cnt)
	{
		vector<PII> ed1, ed2;
		for (auto t : ed)
		{
			if (t.first == num || t.second == num) ed2.push_back(t);
			else ed1.push_back(t);
		}
		int idx = 0;
		while (cnt -- )
		{
			ans.push_back(ed1[idx ++ ]);
			ans.push_back({num, num});
		}
		int lst = num;
		while (idx < ed1.size())
		{
			int a = ed1[idx].first, b = ed1[idx].second;
			if (a == lst) swap(a, b);
			ans.push_back({a, b});
			lst = b;
			idx ++;
		}
		idx = 0;
		while (idx < ed2.size())
		{
			int a = ed2[idx].first, b = ed2[idx].second;
			if (a == lst) swap(a, b);
			ans.push_back({a, b});
			lst = b;
			idx ++ ;
		}
	};
	while (same.size())
	{
		auto t1 = same.top();
		same.pop();
		
		int cnt1 = t1.first, num1 = t1.second;
		if (num1 != lst)
		{
			ans.push_back({num1, num1});
			if (cnt1 > 1) same.push({cnt1 - 1, num1});
			lst = num1;
		}
		else
		{
			if (same.size() == 0)
			{
				work(num1, cnt1);
				for (int i = 1; i <= n; i ++ ) cout << ans[i].first << ' ' << ans[i].second << '\n';
				return;
			}
			else
			{
				auto t2 = same.top();
				same.pop();
				same.push(t1);
				int cnt2 = t2.first, num2 = t2.second;
				ans.push_back({num2, num2});
				if (cnt2 > 1) same.push({cnt2 - 1, num2});
				lst = num2;
			}
		}
	}
	int idx = 0;
	while (idx < ed.size())
	{
		int a = ed[idx].first, b = ed[idx].second;
		if (a == lst) swap(a, b);
		ans.push_back({a, b});
		idx ++ ;
		lst = b;
	}
	for (int i = 1; i <= n; i ++ ) cout << ans[i].first << ' ' << ans[i].second << '\n';
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t = 1;
	// cin >> t;
	while (t--)
	{
		solve();
	}
}

J - Rigged Games(倍增)

  • 对于每个位置求出从该位置开始进行一小局之后的胜负,以及下一步从哪个位置开始执行
  • 用倍增实现, n x t [ i ] [ j ] nxt[i][j] nxt[i][j] 表示从 i i i 开始进行 2 j 2^j 2j 轮到达的位置, r e s [ i ] [ j ] res[i][j] res[i][j] 表示从 i i i 开始进行 2 j 2^j 2j a a a b b b 分别的得分
#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 1e6 + 10;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
	int n, a, b;
	string s;
	cin >> n >> a >> b >> s;
	vector<vector<int>> nxt(n, vector<int>(21));
	vector<vector<PII>> res(n, vector<PII>(21));
	for (int i = 0; i < n; i++) nxt[i][0] = (i + 1) % n;
	for (int i = 0; i < n; i++)
	{
		if (s[i] == '1') res[i][0] = {1, 0};
		else res[i][0] = {0, 1};
	}

	auto work = [&](int u)
	{
		for (int i = 1; i < 20; i++)
		{
			for (int j = 0; j < n; j++)
			{
				nxt[j][i] = nxt[nxt[j][i - 1]][i - 1];
				res[j][i].first = res[j][i - 1].first + res[nxt[j][i - 1]][i - 1].first;
				res[j][i].second = res[j][i - 1].second + res[nxt[j][i - 1]][i - 1].second;
			}
		}
		vector<int> nnxt(n), nres(n);
		for (int i = 0; i < n; i++)
		{
			int now = i, as = 0, bs = 0;
			for (int j = 19; j >= 0; j--)
			{
				if (as + res[now][j].first < u && bs + res[now][j].second < u)
					as += res[now][j].first, bs += res[now][j].second, now = nxt[now][j];
			}
			nnxt[i] = nxt[now][0], nres[i] = res[now][0].first;
		}
		for (int i = 0; i < n; i++)
		{
			if (nres[i]) res[i][0] = {1, 0};
			else res[i][0] = {0, 1};
			nxt[i][0] = nnxt[i];
		}
	};

	work(a);
	work(b);
	for (int i = 0; i < n; i++) cout << res[i][0].first;
	cout << '\n';
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t = 1;
	// cin >> t;
	while (t--)
	{
		solve();
	}
}

L - Sudoku and Minesweeper(签到)

  • 保留一个处在中间的 8 8 8 即可
#include <bits/stdc++.h>

using namespace std;

#define int long long
using i64 = long long;

typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;

const int N = 1e6 + 10;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;

void solve()
{
	vector<string> g(10);
	for (int i = 1; i <= 9; i ++ )
	{
		cin >> g[i];
		g[i] = " "  + g[i];
	}
	vector<vector<char>> ans(10, vector<char>(10));
	for (int i = 1; i <= 9; i ++ )
	{
		for (int j = 1; j <= 9; j ++ )
		{
			ans[i][j] = '*';
		}
	}
	bool flag = false;
	for (int i = 2; i <= 8; i ++ )
	{
		for (int j = 2; j <= 8; j ++ )
		{
			if (g[i][j] == '8')
			{
				ans[i][j] = '8';
				flag = true;
				break;
			}
		}
		if (flag) break;
	}
	for (int i = 1; i <= 9; i ++ )
	{
		for (int j = 1; j <= 9; j ++ )
		{
			cout << ans[i][j];
		}
		cout << '\n';
	}
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int t = 1;
	// cin >> t;
	while (t--)
	{
		solve();
	}
}
  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Texcavator

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值