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

[toc]

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$ 可能明天起來補?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章