比赛链接:

https://ac.nowcoder.com/acm/contest/38727

E.Everyone is bot

题意:

\(n\) 个人在群里复读,第 \(i\) 个人在第 \(j\) 个复读会获得 \(a_{i, j}\) 瓶冰红茶。
一次复读的过程如下:
每一轮按照编号从小到大的顺序,每一个人可以选择复读或者不复读,如果一个人在前面几轮复读过了,他不能再复读了。如果某一轮没有人选择复读,那么这次复读结束。
如果某个人是所有复读的人中倒数第 \(p\) 个复读的,那么他会被禁言,无法获得冰红茶,同时要倒付 154 瓶冰红茶。
每个人都想获得更多的冰红茶,问一次复读过后,每个人最多能获得多少冰红茶。

思路:

当有 \(n - p\) 个人已经复读了,那么最后 \(p\) 个人会互相牵制,谁也不想做倒数第 \(p\) 个,同理在这之前的 \(p\) 个人也会互相牵制,所以最后的答案就是前 \(n\) % \(p\) 个人能获得冰红茶。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL n, p;
	cin >> n >> p;
	vector a(n + 1, vector<LL>(n + 1));
	for (int i = 1; i <= n; i ++ )
		for (int j = 1; j <= n; j ++ )
			cin >> a[i][j];
	for (int i = 1; i <= n; i ++ ){
		if (i <= n % p) cout << a[i][i];
		else cout << 0;
		cout << " \n"[i == n];
	}
	return 0;
}

H.Here is an Easy Problem of Zero-chan

题意:

给定一棵 \(n\) 个节点的树,\(q\) 次询问,每次给定一个 \(x\),求 \(\prod_{i = 1}^{n} lca(x, i)\) 的后缀零的数量。

思路:

一个数的后缀零其实就是它分解之后有多少个 10,也等价于分解后 2 和 5 的数量中的小的那个值。
记节点 \(u\) 分解后 2 的数量为 \(cnt_2\),5 的数量为 \(cnt_5\),子树大小为 \(sz_u\)
对于 \(u\),它及自己的子树节点的 \(lca\) 都是自己,所以 2 的贡献就是 \(sz_u * cnt_2\),5 的贡献同理。
接下来考虑剩余的节点,从 \(u\) 到根节点的路径上,\(u\) 与这些节点的 \(lca\) 都是它们自己,同时 \(u\) 与它们的其它分支上的子树节点的 \(lca\) 也是它们自己。
记节点 \(u\) 除子树外其它节点总和的 \(lca\) 分解后的 2 的数量为 \(pre_2\)
对于子节点 \(v\)\(pre2_v = pre2_u + (sz_u - sz_v) * cnt2_u\)

前一部分计算的是红色以上的数量,后一部分计算的是蓝色部分的数量。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL n, q;
	cin >> n >> q;
	vector < vector <LL> > e(n + 1);
	for (int i = 0; i < n - 1 ; i ++ ){
		LL u, v;
		cin >> u >> v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	vector <LL> cnt2(n + 1), cnt5(n + 1), sum2(n + 1), sum5(n + 1), sz(n + 1);
	function<void(LL, LL)> dfs1 = [&](LL u, LL fa){
		sz[u] = 1;
		LL t = u;
		while(t % 2 == 0){
			t /= 2;
			cnt2[u] ++ ;
		}
		t = u;
		while(t % 5 == 0){
			t /= 5;
			cnt5[u] ++ ;
		}
		for (auto v : e[u]){
			if (v == fa) continue;
			dfs1(v, u);
			sz[u] += sz[v];
		}
		sum2[u] = cnt2[u] * sz[u];
		sum5[u] = cnt5[u] * sz[u];
	};
	dfs1(1, 0);
	vector <LL> pre2(n + 1), pre5(n + 1);
	function<void(LL, LL)> dfs2 = [&](LL u, LL fa){
		for (auto v : e[u]){
			if (v == fa) continue;
			pre2[v] += pre2[u] + (sz[u] - sz[v]) * cnt2[u];
			pre5[v] += pre5[u] + (sz[u] - sz[v]) * cnt5[u];
			dfs2(v, u);
		}
	};
	dfs2(1, 0);
	while(q -- ){
		LL x;
		cin >> x;
		cout << min(sum2[x] + pre2[x], sum5[x] + pre5[x]) << "\n";
	}
	return 0;
}

J.Jellyfish and its dream

题意:

长为 \(n\) 的序列,值域为 0 ~ 2,如果 \((a_i + 1)\) mod 3 = \(a_{(i + 1) \% n}\),可以让 \(a_i = (a_i + 1)\) mod 3。问能否经过操作使得所有元素相等。

思路:

先对数组做一个差分。
差分后,一次操作可以让 (2, 1) 变成 (0, 0),即可以通过 1 来消除 2。
(1, 1)可以变成(0,1),1 可以自消。
(0, 1)可以变成(1, 0),1 的位置可换。
所以 0 是没用的,只需要考虑 1 和 2 的数量,只要 1 的数量 >= 2 即可,让 2 和 1 相消。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	LL n;
	cin >> n;
	vector <LL> a(n);
	for (int i = 0; i < n; i ++ )
		cin >> a[i];
	vector <LL> cnt(3);
	for (int i = 0; i < n; i ++ ){
		LL x = (a[i] - a[(i - 1 + n) % n] + 3) % 3;
		cnt[x] ++ ;
	}
	if (cnt[1] >= cnt[2]) cout << "Yes\n";
	else cout << "No\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	LL T = 1;
	cin >> T;
	while(T -- ){
		solve();
	}
	return 0;
}

M.Maimai DX 2077

题意:

有四种类型的音符,每个音符有五种判定,每个音符的每一种判定都有一个标准分,只有 \(break\) 音符有额外分。
\(A\) 为所有判定都是 c.p 的标准分,\(A_0\) 为自己真实获得的标准分。
\(B\) 为所有判定都是 c.p 的额外分,\(B_0\) 为自己真实获得的额外分。
输出 \(\frac{A}{A_0} + \frac{B}{B_0} * 0.01\)

思路:

直接模拟就行。

代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	cout << fixed << setprecision(15);
	vector c(4, vector <int>(5));
	for (int i = 0; i < 4; i ++ )
		for (int j = 0; j < 5; j ++ )
			cin >> c[i][j];
	double A = 0, A0 = 0;
	A0 = c[0][0] + c[0][1] + 0.8 * c[0][2] + 0.5 * c[0][3];
	A = c[0][0] + c[0][1] + c[0][2] + c[0][3] + c[0][4];
	
	A0 += 2 * (c[1][0] + c[1][1]) + 1.6 * c[1][2] + c[1][3];
	A += 2 * (c[1][0] + c[1][1] + c[1][2] + c[1][3] + c[1][4]);
	
	A0 += 3 * (c[2][0] + c[2][1]) + 2.4 * c[2][2] + 1.5 * c[2][3];
	A += 3 * (c[2][0] + c[2][1] + c[2][2] + c[2][3] + c[2][4]);
	
	A0 += 5 *(c[3][0] + c[3][1]) + 2.5 * c[3][2] + 2 * c[3][3];
	A += 5 * (c[3][0] + c[3][1] + c[3][2] + c[3][3] + c[3][4]);
	
	double B = 0, B0 = 0;
	B0 = c[3][0] + 0.5 * c[3][1] + 0.4 * c[3][2] + 0.3 * c[3][3];
	B = c[3][0] + c[3][1] + c[3][2] + c[3][3] + c[3][4];
	
	cout << A0 / A * 100 + B0 / B << "\n";
	return 0;
}
posted on 2022-08-22 19:24  Hamine  阅读(43)  评论(0编辑  收藏  举报