比赛链接:

https://codeforces.com/gym/102769

A. A Greeting from Qinhuangdao

题意:

\(r\) 个红球和 \(b\) 个蓝球,拿两个球,问全是红球的概率。

思路:

\(n\) 个球拿两个的方案为 \(C_n^2\)
求出拿两个红球的方案和拿所有球的方案,除一个公约数即可。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	int a, b;
	cin >> a >> b;
	LL p = a * (a - 1) / 2, q = (a + b) * (a + b - 1) / 2;
	LL d = __gcd(p, q);
	cout << p / d << "/" << q / d << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int T = 1;
	cin >> T;
	for (int i = 1; i <= T; i ++ ){
		cout << "Case #" << i << ": ";
		solve();
	}
	return 0;
}

E. Exam Results

题意:

\(n\) 个学生参加考试,第 \(i\) 个学生好心情的时候能拿 \(a_i\) 分,坏心情的时候能拿 \(b_i\) 分(\(b_i <= a_i\)),当某个学生的成绩 >= 最高分 * \(p\)% 的时候,他能通过考试,问最多能有几个学生通过考试。

思路:

先将所有分数加入 vector 中,然后排序,通过双指针枚举最高分和及格线,当最高分 >= 所有人都是坏心情的时候的最大值时,它才是答案,输出最大值。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	LL n, p;
	cin >> n >> p;
	vector < pair<LL, int> > v;
	LL lim = 0;
	for (int i = 0; i < n; i ++ ){
		LL a, b;
		cin >> a >> b;
		v.push_back({a, i});
		v.push_back({b, i});
		lim = max(lim, b);
	}
	sort(v.begin(), v.end());
	vector <int> cnt(n);
	int ans = 0, cur = 0;
	for (int i = 0, j = 0; i < 2 * n; i ++ ){
		while(j < i && 100 * v[j].first < p * v[i].first){
			cnt[v[j].second] -- ;
			if (cnt[v[j].second] == 0) cur -- ;
			j ++ ;
		}
		if (cnt[v[i].second] == 0) cur ++ ;
		cnt[v[i].second] ++ ;
		if (v[i].first >= lim) ans = max(ans, cur);
	}
	cout << ans << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int T = 1;
	cin >> T;
	for (int i = 1; i <= T; i ++ ){
		cout << "Case #" << i << ": ";
		solve();
	}
	return 0;
}

F. Friendly Group

题意:

\(n\) 个人,\(m\) 对关系,表示 \(u\)\(v\) 是朋友,现在选择一些人参加会议,如果某对关系中两个人都参与了会议,可以获得一点分数,如果只有一个人参与了会议,会扣一点分数,参加了几个人会扣几分,问最大能获得多少分。

思路:

现在选择了点 \(u\),考虑选不选 \(v\)
不选的话,扣一分,因为一对关系中有一个人没参加。
选了的话,加一分,然后扣一分,因为选择了关系,但是多选了一个点,所以得 0 分。
显然,所有连通的点都要选。一个连通块的答案就是连通块中的边减去点。将所有连通块得分大于 0 的加起来就是答案。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	int n, m;
	cin >> n >> m;
	vector < vector<int> > e(n + 1);
	for (int i = 1; i <= m; i ++ ){
		int u, v;
		cin >> u >> v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	vector <int> vis(n + 1);
	int sum, ver;
	function<void(int)> dfs = [&](int u){
		sum += e[u].size();
		ver ++ ;
		for (auto v : e[u]){
			if (vis[v]) continue;
			vis[v] = 1;
			dfs(v);
		}
	};
	int ans = 0;
	for (int i = 1; i <= n; i ++ ){
		if (vis[i]) continue;
		sum = ver = 0;
		vis[i] = 1;
		dfs(i);
		ans += max(0, sum / 2 - ver);
	}
	cout << ans << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int T = 1;
	cin >> T;
	for (int i = 1; i <= T; i ++ ){
		cout << "Case #" << i << ": ";
		solve();
	}
	return 0;
}

G. Good Number

题意:

给定 \(n\)\(k\),判断不超过 \(n\) 的数中满足 \(\lfloor \sqrt[k]x\rfloor\) 能整除 \(n\) 的数的数量。

思路:

逆过来想,\([x^k, x^{k + 1})\) 的数中开了 \(k\) 次根号之后,都是 \(x\),即这个区间中 \(x\) 的倍数都是可以的,跑个暴力就行。
注意两个特殊情况,\(k = 1\) 的时候,所有数都是可以的,\(k >= 30\) 的时候,开完根号之后都是 1,所有数也都是可以的。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
void solve(){
	LL n, k;
	cin >> n >> k;
	if (k == 1 || k >= 30){
		cout << n << "\n";
	}
	else{
		LL ans = 0, x = 1;
		for (int i = 2; x <= n; i ++ ){
			LL y = 1;
			for (int j = 1; j <= k; j ++ )
				y = min(y * i, n + 1);
			ans += (y - 1) / (i - 1) - (x - 1) / (i - 1);
			x = y;
		}
		cout << ans << "\n";
	}
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int T = 1;
	cin >> T;
	for (int i = 1; i <= T; i ++ ){
		cout << "Case #" << i << ": ";
		solve();
	}
	return 0;
}

K. Kingdom's Power

题意:

有一棵树,根节点有无数军队,每次可以让一支军队向相邻的节点进发,当军队到达一个节点的时候,这个节点就被攻克,问最少移动多少次可以让攻克。

思路:

每个节点的军队只可能从根节点或者另一个叶节点过来,于是对每个节点按照深度排序,优先走深度小的节点。

代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 1e6 + 10;
int dep[N], mxdep[N];
void solve(){
	int n;
	cin >> n;
	vector < vector<int> > e(n + 1);
	for (int v = 2; v <= n; v ++ ){
		int u;
		cin >> u;
		e[u].push_back(v);
	}
	function<void(int, int)> dfs1 = [&](int u, int depth){
		mxdep[u] = dep[u] = depth;
		for (auto v : e[u]){
			dfs1(v, depth + 1);
			mxdep[u] = max(mxdep[u], mxdep[v]);
		}
		sort(e[u].begin(), e[u].end(), [](int a, int b){
			return mxdep[a] < mxdep[b];
		});
	};
	dfs1(1, 0);
	int pre = 0, ans = 0;
	function<void(int, int)> dfs2 = [&](int u, int fa){
		if (u != 1){
			if (!pre) ans += dep[u];
			else ans += min(dep[u], dep[pre] - dep[fa] + 1);
			pre = u;
		}
		for (auto v : e[u]){
			if (v == fa) continue;
			dfs2(v, u);
		}
	};
	dfs2(1, 0);
	cout << ans << "\n";
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	int T = 1;
	cin >> T;
	for (int i = 1; i <= T; i ++ ){
		cout << "Case #" << i << ": ";
		solve();
	}
	return 0;
}
posted on 2022-09-10 23:08  Hamine  阅读(100)  评论(0编辑  收藏  举报