本次比赛翻译出现了大问题,想大家道歉。

同时一些同学反映已经做过,下次个人赛会再拉更早的题目。

A - ABC222A

签到,不讲。

int main() {
	int x;
	scanf("%d", &x);
	printf("%04d", x);
	return 0;
}

B - CF1395A

题目大意

给定四种颜色的球,允许把三个红、绿、蓝的球转换为三个白色的,问是否存在方法使得能够排成回文的一列。

分析

注意到四种颜色个数只有 $0$ 个或 $1$ 个奇数时,才能够摆成回文的一列。

而转换对四种颜色都意味着奇数变偶数,偶数变奇数。即转换两次又回到原先的奇偶序列,故只用变换一次。

bool check(const vector<int> &v) {
	vector<int> cnt(2);
	for (auto i : v) {
		if (i < 0)
			return false;
		cnt[i % 2]++;
	}
	return cnt[1] <= 1;
}

int main() {
	int T;
	cin >> T;
	while (T--) {
		vector<int> v1(4), v2(4);
		for (int i = 0; i < 4; i++)
			cin >> v1[i], v2[i] = v1[i];
		v2[0]--, v2[1]--, v2[2]--, v2[3] += 3;

		if (check(v1) || check(v2)) {
			printf("Yes\n");
		} else {
			printf("No\n");
		}
	}
	return 0;
}

C - CF1393B

题目大意

给定一些长度,问是否能够组成一个长方形和一个正方形。

分析

分类需要分的很仔细。

  • 如果有 $(2, 2, 2, 2)$,那么可以拼成两个长方形。
  • 如果有 $(2, 2, 4)$,那么可以拼成一个长方形和一个正方形。
  • 如果有 $(2, 6)$,那么可以拼成一个长方形和一个正方形。
  • 如果有 $(4, 4)$,那么可以拼成两个正方形。
  • 如果有 $(8)$,那么可以拼成两个正方形。

如此

int main() {
	int n;
	cin >> n;
	vector<int> a(N + 1);
	for (int i = 1; i <= n; i++) {
		int t;
		cin >> t;
		a[t]++;
	}
	vector<int> num(10);
	auto add = [&](int t) {
		for (int j = 1; j <= min(t, 8); j++) {
			num[j]++;
		}
	};
	auto sub = [&](int t) {
		for (int j = 1; j <= min(t, 8); j++) {
			num[j]--;
		}
	};
	for (int i = 1; i <= N; i++) {
		add(a[i]);
	}

	int Q;
	cin >> Q;
	while (Q--) {
		string op;
		int x;
		cin >> op >> x;
		sub(a[x]);
		if (op[0] == '+') {
			a[x]++;
		} else {
			a[x]--;
		}
		add(a[x]);
		if (num[8] >= 1) {
			printf("YES\n");
		} else if (num[6] >= 1 && num[2] >= 2) {
			printf("YES\n");
		} else if (num[4] >= 1 && num[2] >= 3) {
			printf("YES\n");
		} else if (num[4] >= 2) {
			printf("YES\n");
		} else {
			printf("NO\n");
		}
	}
	return 0;
}

D - CF908C

题目大意

有 $n$ 个半径为 $r$ 的盘子,当盘子碰到地面或者另一个盘子时立刻停止。给定每个盘子的 $x_i$,求解 $y_i$。

分析

对每一个盘子,计算其与之前所有盘子的距离即可,解一个二次方程。

int main() {
	int n;
	double r;
	cin >> n >> r;
	vector<double> x(n), y(n);
	for (int i = 0; i < n; i++) {
		cin >> x[i];
		y[i] = r;
		for (int j = 0; j < i; j++) {
			double tx = x[i] - x[j];
			double delta = 4 * r * r - tx * tx;
			if (delta + 1E-8 >= 0) {
				y[i] = max(y[j] + sqrt(delta), y[i]);
			}
		}
		printf("%.10lf ", y[i]);
	}
	return 0;
}

E - CF1395C

题目大意

给定两个非负的整数数组 $a_1,\cdots, a_n$ 和 $b_1,\cdots,b_m$。

对于每个 $i(1 \leqslant i \leqslant n)$,你可以选择一个 $j(1 \leqslant j \leqslant m)$ 并让

$$ c_i = a_i \land b_j $$

需要让 $ c_1 \lor \cdots \lor c_n $ 尽可能小。

分析

注意到答案不可能超过 $512$,可以考虑枚举答案。

int main() {
	int n, m;
	cin >> n >> m;
	vector<int> va(n), vb(m);
	for (int i = 0; i < n; i++) {
		cin >> va[i];
	}
	for (int i = 0; i < m; i++) {
		cin >> vb[i];
	}
	vector<int> vis(n);
	for (int o = 0; o < 512; o++) {
		bool f1 = true;
		for (int i = 0; i < n; i++) {
			bool f2 = false;
			for (int j = 0; j < m; j++) {
				int x = va[i] & vb[j];
				if ((o | x) == o) {
					f2 = true;
					break;
				}
			}
			if (!f2) {
				f1 = false;
				break;
			}
		}
		if (f1) {
			cout << o << "\n";
			break;
		}
	}
	return 0;
}

F - CF911D

题目大意

给定一个排列,支持操作 $[l,r]$ 翻转,问每次操作后排列的奇偶性。

分析

回想一下线性代数的知识,交换两个数后,排列奇变偶,偶变奇。

而区间翻转可以分解为交换两个数,故答案与翻转的长度有关。

int main() {
	int n;
	cin >> n;
	vector<int> v(n);
	for (int i = 0; i < n; i++)
		cin >> v[i];
	int ans = 0;
	for (int i = 0; i < n; i++) {
		for (int j = i + 1; j < n; j++) {
			if (v[i] > v[j])
				ans++;
		}
	}
	ans %= 2;
	int Q;
	cin >> Q;
	while (Q--) {
		int l, r;
		cin >> l >> r;
		int num = (r - l + 1) / 2;
		ans = (ans + num) % 2;
		if (ans == 1)
			printf("odd\n");
		else
			printf("even\n");
	}
	return 0;
}

G - 2020 CCPC 长春 D

本题是一场区域赛的真题,是该场的第二签到,过题人数 289/320。本题用来给大家对照自身水平。

分析

注意到 $a_i = c^{\operatorname{popcount}(i)}$,使用一些数位 DP 的技巧即可求和。

H - ABC212G

分析

本题考察了 $\varphi(n)$ 函数性质的简单应用。

因为给定的 $p$ 一定是质数,也就一定存在原根 $g$,从而可以取离散对数。即

$$ n \log x \equiv \log y \pmod {p-1} $$

那么对于每个 $\log x$,存在的 $\log y$ 的个数为 $\frac{p-1}{\gcd(\log x, p - 1)}$,那么求和即是答案

$$ \begin{aligned} \sum_{a=1}^n \frac{p - 1}{\gcd(a, p - 1)} &= \sum_{u \mid p - 1}\sum_{a=1}^n \frac{p-1}{u}[\gcd(a, p - 1) = u] \\ & = \sum_{u \mid p - 1} \frac{p-1}{u} \varphi\left(\frac{p-1}{u}\right)\\ &= \sum_{u \mid p - 1} u \varphi(u) \end{aligned} $$

令 $f(n) = \sum_{u \mid n} u \varphi(u)$,注意到 $f$ 是一个积性函数,我们可以直接计算其在质数处的点值

$$ f(p^e) = 1 + \sum_{i=1}^e p^i \varphi(p^i) = 1 + (p-1) \sum_{i=1}^e p^{2i - 1} $$

用等比数列还是直接求和都行,因为 $e$ 不会很大。最后用因式分解合并答案即可。

const int P = 998244353;
using pll = pair<ll, ll>;
 
vector<pll> factor(ll n) {
	vector<pll> ret;
	for (ll i = 2; 1ll * i * i <= n; i++) {
		int cnt = 0;
		while (n % i == 0) {
			n /= i, cnt++;
		}
		if (cnt > 0) {
			ret.push_back({i, cnt});
		}
	}
	if (n > 1) {
		ret.push_back({n, 1});
	}
	return ret;
}
 
int main() {
	ll pp, ans = 1;
	cin >> pp;
	for (auto [p, e] : factor(pp - 1)) {
		ll pk = 1, tsum = 1;
		p %= P;
		for (int k = 1; k <= e; k++) {
			tsum += 1ll * pk * pk % P * (p - 1) % P * p % P;
			pk = 1ll * pk * p % P;
		}
		ans = 1ll * ans * tsum % P;
	}
	cout << (ans + 1) % P;
	return 0;
}