vp链接:https://codeforces.com/gym/104417
A. Orders
根据题意模拟,分别按照 a,b 排序,排序后再判断该订单是否能完成。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 105;
int n, k;
struct node { int a, b; } p[N];
inline int read() {
	int x = 0, f = 1; char c = getchar();
	while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
bool cmp(node x, node y) {
    if (x.a == y.a) return x.b < y.b;
    return x.a < y.a;
}
void solve() {
    n = read(), k = read();
    for (int i = 1; i <= n; i++) p[i].a = read(), p[i].b = read();
    sort(p + 1, p + n + 1, cmp);
    int res = 0, lst = 0;
    for (int i = 1; i <= n; i++) {
        res += (p[i].a - lst) * k;
        if (res < p[i].b) {
            puts("No");
            return;
        }
        res -= p[i].b, lst = p[i].a;
    }
    puts("Yes");
}
signed main() {
    int t = read();
    while (t--) {
        solve();
    }
	return 0;
}E. Math Problem
很容易发现先进行操作一再进行操作二是无效的,所以只有两种操作方式:
- 一直进行操作一
- 先进行操作而再进行操作一
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n, k, m, a, b;
void solve() {
	if (k == 1) {
		if (n % m == 0) cout << 0 << '\n';
		else cout << -1 << '\n';
		return;
	}
	int ans = LLONG_MAX;
	for (int i = 0; ;i++, n /= k) {
		if (n == 0) {
			ans = min(ans, i * b);
			break;
		}
		__int128_t l = n, r = n;
		int sum = b * i;
		while (r / m == l / m && l % m != 0) {
			l = l * k;
			r = r * k + k - 1;
			sum += a;
		}
		ans = min(ans, sum);
	}
	cout << ans << '\n';
}
signed main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int t;
	cin >> t;
	while (t--) {
		cin >> n >> k >> m >> a >> b;
		solve();
	}
	return 0;
}G. Matching
 等价于 
,不妨设 
,所有有边连通的点 
 一定相同。从无向图中选出一些边,使得任意两条边都没有公共节点,等价于成对地选出 b 值相同的点。由于连接 i 和 j 的节点边权为 
,要最大边权和,其实等价于求成对选出的点的最大点权和。
可以先按照  进行排序,
 相同则按照 
 从小到大进行排序。对于 b 相同的节点,从前往后成对的选出点权和大于 0 的点,记录点权和。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5 + 10;
int n;
struct node { int a, b, id; } p[N];
inline int read() {
	int x = 0, f = 1; char c = getchar();
	while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
bool cmp(node x, node y) {
	if (x.b == y.b) return x.a > y.a;
	return x.b < y.b;
}
signed main() {
	int t = read();
	while (t--) {
		n = read();
		for (int i = 1; i <= n; i++) {
			p[i].a = read();
			p[i].id = i, p[i].b = i - p[i].a;
		}
		sort(p + 1, p + n + 1, cmp);
		int ans = 0LL;
		for (int i = 1; i <= n; i++) {
			if (i + 1 <= n && p[i].b == p[i + 1].b) {
				if (p[i].a + p[i + 1].a > 0) {
					ans += p[i].a + p[i + 1].a;
					i++;
				}
			}
		}
		printf("%lld\n", ans);
	}
	return 0;
}L. Puzzle: Sashigane
构造题。围绕黑色方格利用两条边长度相等的 L 型进行覆盖,可以使得黑色方格以及白色方格覆盖的区域有 1 x 1 变成 2 x 2,2 x 2 变成 3 x 3,......,最后变成 n x n。
每一次利用 L 型进行覆盖的时候,只需要在原有覆盖区域外四角的任意一角作为 L 型的拐点即可。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
int n;
struct node { int r, c, h, w; } ans[N];
inline int read() {
	int x = 0, f = 1; char c = getchar();
	while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
	while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
bool check(int x, int y) {
	if (x >= 1 && x <= n && y >= 1 && y <= n) return true;
	return false;
}
void dfs(int x, int y, int len) {
	if (len > n) return;
	int l = len - 1;
	if (check(x - l, y + l)) {
		ans[l] = (node){x - l, y + l, l, -l};
		dfs(x, y, len + 1);
		return;
	}
	if (check(x - l, y - 1)) {
		ans[l] = (node){x - l, y - 1, l, l};
		dfs(x, y - 1, len + 1);
		return;
	}
	if (check(x + 1, y + l)) {
		ans[l] = (node){x + 1, y + l, -l, -l};
		dfs(x + 1, y, len + 1);
		return;
	}
	if (check(x + 1, y - 1)) {
		ans[l] = (node){x + 1, y - 1, -l, l};
		dfs(x + 1, y - 1, len + 1);
		return;
	}
}
int main() {
	n = read(); int x = read(), y = read();
	dfs(x, y, 2);
	printf("Yes\n%d\n", n - 1);
	for (int i = 1; i < n; i++) printf("%d %d %d %d\n", ans[i].r, ans[i].c, ans[i].h, ans[i].w);
	return 0;
}


















