Codeforces Round #630 (Div. 2) 部分题解

Codeforces Round #630 (Div. 2)

A. Exercising Walk

题意:一只猫初始在点 \((x,y)\) ,你需要移动它 \(a+b+c+d\) 次,其中 \(a\) 次向左移动一个单位,\(b\) 次向右移动一个单位,\(c\) 次向下移动一个单位,\(d\) 次向上移动一个单位,你可以任意安排移动次序,询问这只猫能否每次移动后均位于 \((x_1,y_1)\)\((x_2,y_2)\) 的矩形内。

分析:最终位置必定是 \((x+b-a,y+d-c)\) ,除此以外特判一下动一次就会出界的情况。

#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define rep(i, a, b) for (long long i = a; i <= b; ++i)
#define mp make_pair
#define SIZE 105
#define eps 1e-9
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
int n, k, t;

int main() {
	io(); cin >> t;
	rep(i, 1, t) {
		int a, b, c, d;
		cin >> a >> b >> c >> d;
		int x, y, xa, xb, ya, yb;
		cin >> x >> y >> xa >> ya >> xb >> yb;
		x += b - a; y += d - c;
		if (xa == xb && (a || b)) cout << "NO\n";
		else if (ya == yb && (c || d)) cout << "NO\n";
		else if (x >= xa && x <= xb && y >= ya && y <= yb) cout << "YES\n";
		else cout << "NO\n";
	}
}

B. Composite Coloring

题意:用最多不超过 \(11\) 种颜色,对一个数组 \(a_n\) 染色(\(a_i\leq 1000\) 且不为质数),并满足同色的任意数字不互质。

分析:直接暴力筛。

#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define rep(i, a, b) for (long long i = a; i <= b; ++i)
#define mp make_pair
#define SIZE 105
#define eps 1e-9
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
int n, k, t, cnt;

int main() {
	io(); vector<int> c(1001, 0);
	rep(i, 2, 1000) {
		if (!c[i]) c[i] = ++cnt;
		int num = c[i];
		for (int j = i + i; j <= 1000; j += i) {
			if (c[j]) continue;
			c[j] = num;
		}
	}
	cin >> t;
	rep(ii, 1, t) {
		cin >> n;
		vector<int> a(n);
		map<int, int> MP;
		int p = 0;
		for (auto& i : a) cin >> i;
		for (auto i : a) {
			if (MP.count(c[i])) continue;
			MP[c[i]] = ++p;
		}
		cout << p << '\n';
		for (auto i : a) cout << MP[c[i]] << ' ';
		cout << '\n';
	}
}

C. K-Complete Word

题意:判断一个字符串最多修改几个字符可以变成 \(K-Complete\) 的。\(K-Complete\) 指的是:

  1. 该字符串为回文串;
  2. 该字符串的周期为 \(K\)

分析:直接并查集,把所有必须相同的字符位置合并,然后找到这些位置中出现最多次的字符。

#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define rep(i, a, b) for (long long i = a; i <= b; ++i)
#define mp make_pair
#define SIZE 200010
#define eps 1e-9
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
ll t, n, k;
struct UnionSet { //并查集
	int pa[SIZE];
	void init(int n) {
		for (int i = 1; i <= n; i++) pa[i] = i;
	}
	int find(int x) {
		return pa[x] == x ? x : pa[x] = find(pa[x]);
	}
	bool IsSame(int x, int y) { return find(x) == find(y); }
	int union_vertices(int x, int y) {
		int xr = find(x), yr = find(y);
		if (xr != yr) {
			pa[yr] = xr;
			return 1;
		}
		return 0;
	}
} U;

int main() {
	io(); cin >> t;
	rep(ii, 1, t) {
		cin >> n >> k;
		string s; cin >> s;
		U.init(n);
		int ans = 0;
		rep(i, 0, (k - 1))
			for (int j = i + k; j < n; j += k)
				U.union_vertices(i, j);
		rep(i, 0, (n >> 1)) U.union_vertices(i, n - 1 - i);
		map<int, vector<int> > MP;
		rep(i, 0, (n - 1)) {
			if (MP.count(U.find(i))) MP[U.find(i)][s[i] % 26]++;
			else {
				MP[U.find(i)].resize(26);
				MP[U.find(i)][s[i] % 26]++;
			}
		}
		for (auto i : MP) {
			int tmp = 0;
			for (auto j : i.second) tmp = max(tmp, j);
			ans += tmp;
		}
		cout << n - ans << '\n';
	}
}

D. Walk on Matrix

题意:涉及伪代码,不翻了。

分析:构造。先设 \(n\) 是比 \(k\) 大的一个数,并且是 \(2\) 的幂次;比如:若 \(k=14\) ,则 \(n=16\) 。然后构造这么一个矩阵:

\[\left[ \begin{array}{cccc} n+k & n & n \\ k & n & n+k \\ k & n + k & k \end{array} \right]\]

如果按照题目中的 \(dp\) ,跑出的结果将会是 \(0\) ,而最大值是 \(k\) 。最后特判 \(k=0\) 的情况即可。

#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define rep(i, a, b) for (long long i = a; i <= b; ++i)
#define mp make_pair
#define SIZE 105
#define eps 1e-9
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
int n, m, k;
int vec[3][3];
int main() {
	io(); cin >> k;
	if (!k) cout << "1 1\n1";
	else {
		int tp = 1;
		while (tp <= k) tp <<= 1;
		vec[0][0] = vec[2][1] = vec[1][2] = tp + k;
		vec[0][1] = vec[0][2] = vec[1][1] = tp;
		vec[1][0] = vec[2][0] = vec[2][2] = k;
		cout << "3 3\n";
		rep(i, 0, 2) {
			rep(j, 0, 2) {
				cout << vec[i][j] << ' ';
			}
			cout << '\n';
		}
	}
}

E. Height All the Same

题意:一个 \(N\times M\) 的网格图上的每个网格初始放有高度在 \([L,R]\) 范围内的立方体木块。你每次能在这个网格图中选择一个位置加上 \(2\) 个立方体木块,或者选择两个相邻位置各加上 \(1\) 个木块,询问有几种初始状态能够经过有限次操作是的所有位置的木块高度一致。

分析:因为不论怎么操作,都是给现有的方块堆加上 \(2\) 个方块,因此奇偶性不变。我们假设初始最高的一堆木块高度为 \(H\) ,如果最终能够使得所有位置高度一致,则需要满足:\((NMk+(NMH-\sum pos[i][j]))\% 2=0\) ,其中 \(pos[i][j]\) 指代网格图中位置为 \((i,j)\) 的方块数。

不难发现如果 \(NM\) 为奇数,则上式必然能成立,则方案数为 \((R-L+1)^{NM}\) ;若 \(NM\) 为偶数,则能否变成高度一致取决于 \(NMH-\sum pos[i][j]\) 的奇偶性,又因为此时 \(NM\) 为偶数,因此初始的总方块数若为奇数就必定不行,我们减去初始方块数为奇数的情况即为答案。

#define _CRT_SECURE_NO_WARNINGS
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
#include <bits/stdc++.h>
#define rep(i, a, b) for (long long i = a; i <= b; ++i)
#define mp make_pair
#define SIZE 105
#define eps 1e-9
#define ll long long
using namespace std;
void io() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); }
const ll mod = 998244353;
ll qpow(ll a, ll b, ll mod) { //快速幂 a ^ b % mod
	ll ans = 1;
	while (b) {
		if (b & 1) ans = (ans * a) % mod;
		a = (a * a) % mod;
		b >>= 1;
	}
	return ans;
}

int main() {
	io(); ll n, m, l, r;
	cin >> n >> m >> l >> r;
	if ((n & 1ll) && (m & 1ll)) cout << qpow(r - l + 1, n * m, mod);
	else {
		ll even = r / 2ll - (l - 1ll) / 2ll, odd = r - l + 1ll - even;
		ll ans = (qpow(odd + even, m * n, mod) - qpow(odd - even, m * n, mod) + mod) % mod;
		ans = (ans * qpow(2ll, mod - 2ll, mod)) % mod;
		ans = (qpow(r - l + 1, n * m, mod) - ans + mod) % mod;
		cout << ans;
	}
}

\(F\) 可能明天起来补?

posted @ 2020-04-01 00:45  st1vdy  阅读(652)  评论(0编辑  收藏  举报