CF1792

GamingForces

贪心,从小到大排序。

对于当前怪物,如果血量大于 \(1\),则直接杀死,否则和下一个怪物各扣一滴血。

复杂度 \(O(n\log n)\)

#include <bits/stdc++.h>
using namespace std;
const int N = 100 + 5;
int T, n, a[N]; 
int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> T;
	while (T--) {
		cin >> n;
		for (int i = 1; i <= n; ++i) cin >> a[i];
		sort(a + 1, a + n + 1);
		int cnt = 0;
		for (int i = 1; i <= n; ++i) {
			if (a[i] == 1) {
				--a[i]; --a[i + 1];
				++cnt;
			} else if (a[i] > 1) ++cnt;
		}
		cout << cnt << endl;
	}
	return 0;
}

Stand-up Comedian

还是贪心。

首先我们可以把两人都喜欢的节目 \(a_1\) 安排上,然后一个 \(a_2\) 一个 \(a_3\) 使得两人的心情值不变。

最后把 \(a_2\)\(a_3\)\(a_4\) 中剩下的尽可能安排上。

复杂度 \(O(1)\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int T;
ll a, b, c, d;
int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> T;
	while (T--) {
		cin >> a >> b >> c >> d;
		if (a == 0) {
			cout << 1 << endl;
			continue;
		}
		ll ans = a;
		if (b > c) ans += c * 2, b -= c, c = 0;
		else ans += b * 2, c -= b, b = 0;
		ans += min(a, b + c + d);
		if(b + c + d > a) ++ans;
		cout << ans << endl;
	}
	return 0;
}

Min Max Sort

又是贪心。

我们假设最后选了 \([1,x]\)\([n-x+1,n]\) 中所有的数,完成了序列的排序。

那么只有 \((x,n-x+1)\) 在对应的位置上时才能成立。

于是我们可以记录原始数组中每个数的位置,然后从中间部分向两侧拓展,看 \((x,n-x+1)\) 最长为多少即可。

复杂度 \(O(n)\)

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int T, n, a[N], w[N];
int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> T;
	while (T--) {
		cin >> n;
		for (int i = 1; i <= n; ++i) {
			cin >> a[i];
			w[a[i]] = i;
		}
		int l = n / 2, r = (n + 3) / 2, ans = n / 2;
		while (l >= 1 && w[l] < w[l + 1] && w[r - 1] < w[r]) --l, ++r, --ans;
		cout << ans << endl;
	}
	return 0;
}

Fixed Prefix Permutations

感觉思维难度比 \(C\) 题要小。

我们发现 \(m\) 很小,考虑把一个序列的每个前缀压缩成一个 \(11\) 进制的数(注意是 \(11\) 进制!),然后全部放到 map 里。

然后对于每一个序列,我们只需要找出与其完全匹配的数组 \(x\),即 \(p \cdot x\) 的美丽度为 \(m\)。然后枚举 \(x\) 的前缀,看 map 中中有没有即可。

复杂度 \(O(n\log n)\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 5e4 + 5, N2 = 10 + 5;
int T, n, m, a[N][N2], w[N];
ll val[N];
map<ll, int> mp;
int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> T;
	while (T--) {
		cin >> n >> m;
		mp.clear();
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= m; ++j) {
				cin >> a[i][j];
			}
		}
		for (int i = 1; i <= n; ++i) {
			for (int j = 1; j <= m; ++j) {
				w[a[i][j]] = j;
			}
			ll tmp = 0;
			for (int j = 1; j <= m; ++j) {
				tmp = tmp * 11 + w[j];
				mp[tmp] = 1;
			}
		}
		for (int i = 1; i <= n; ++i) {
			ll tmp = 0, ans = 0;
			for (int j = 1; j <= m; ++j) {
				tmp = tmp * 11 + a[i][j];
				if (mp[tmp]) ans = j;
			}
			cout << ans << endl;
		}
	}
	return 0;
}

Divisors and Table

正着想有点难,我们考虑找到最大的行,然后对应的列就是答案。

首先我们用 \(O(\sqrt m_1+\sqrt m_2)\) 的时间找出 \(m\) 的所有质因数,然后 dfs 出 \(m\) 的所有约数。

定义 \(f_i\)\(i\) 的小于 \(n\) 的所有约数中最大的约数。

枚举 \(i\) 的每个约数 \(j\),可得到转移方程:

\[f_i=\max(f_i,f_{\frac{i}{j}}) \]

那么最后的答案为 \(\sum\limits_{i\vert n}^{n}[\frac{i}{f_i}\le n]\)\(\bigoplus\limits_{i|n}^{n}[\frac{i}{f_i}\le n]\frac{i}{f_i}\)

复杂度 \(O(能过)\)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 5;
ll T, n, m1, m2, p[N], num[N], yue[N], f[N], cnt, cnt2, ans, yh = 0;
map<ll, ll> mp;
void get(ll x) {
	for (ll i = 2; i <= sqrt(x); ++i) {
		while (x % i == 0) {
			++mp[i]; x /= i;
		}
	}
	if (x != 1) ++mp[x];
}
void dfs(int cur, ll val) {
	if (cur > cnt) {
		yue[++cnt2] = val;
		return;
	}
	for (int i = 0; i <= num[cur]; ++i) {
		dfs(cur + 1, val);
		val *= p[cur];
	}
}
int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	cin >> T;
	while (T--) {
		mp.clear(); cnt = cnt2 = ans = yh = 0;
		cin >> n >> m1 >> m2; get(m1); get(m2);
		map<ll, ll>::iterator it;
		for (it = mp.begin(); it != mp.end(); ++it) {
			p[++cnt] = (*it).first;
			num[cnt] = (*it).second;
		}
		dfs(1, 1);
		sort(yue + 1, yue + cnt2 + 1);
		for (int i = 1; i <= cnt2; ++i) f[i] = yue[i] <= n?yue[i]:0;
		for (int i = 1; i <= cnt2; ++i) {
			for (int j = 1; j <= cnt; ++j) if (yue[i] % p[j] == 0) f[i] = max(f[i], f[lower_bound(yue + 1, yue + cnt2 + 1, yue[i] / p[j]) - yue]);
			if (yue[i] / f[i] <= n) {
				++ans;
				yh ^= yue[i] / f[i];
			}
		}
		cout << ans << " " << yh << endl;
	}
	return 0;
}
posted @ 2023-07-17 23:06  HQJ2007  阅读(13)  评论(0编辑  收藏  举报