2023ICPC网络赛第一场 - A D G J L

D

补题链接:
pta
cf

榜单:传送门

题解:知乎链接
感觉知乎的题解已经很充分了,这里仅分享AC代码

LADJG
A 模拟
D 图的连通块
G 树
J 期望?
L 模拟

A Qualifiers Ranking Rules

模拟题给的操作流程,关键在于去重

#include<bits/stdc++.h>
#define ll long long

using namespace std;

void solve(){
	int n, m;
	cin >> n >> m;
	string ss;
	vector<string> s, t;
	map<string, int> qs, qt;
	for(int i = 0; i < n; ++ i){
		cin >> ss;
		if(!qs.count(ss)){
			qs[ss] = 1;
			s.push_back(ss);
		}
	}
	for(int i = 0; i < m; ++ i){
		cin >> ss;
		if(!qt.count(ss)){
			qt[ss] = 1;
			t.push_back(ss);
		}
	}
	int i = 0, j = 0;
	map<string, int> qa;
	while(i < s.size() || j < t.size()){
		if(i < s.size()){
			if(!qa.count(s[i])){
				cout << s[i] << '\n';
				qa[s[i]] = 1;
			}
			++ i;
		}
		if(j < t.size()){
			if(!qa.count(t[j])){
				cout << t[j] << '\n';
				qa[t[j]] = 1;
			}
			++ j;
		}
	}
	return ;
}

signed main(){
	int t = 1;
	// cin >> t;
	while(t --){
		solve();
	}
	return 0;
}

D Transitivity

考虑原无向图构成的所有连通块
如果有连通块不是完全图,将其补成完全图即可,需要补的边数即为 $n * (n - 1) / 2 - m $
如果所有连通块都是完全图,那么我们只需要拿顶点数最少的两个连通块将其点两两联通即可

#include<bits/stdc++.h>
#define ll long long

using namespace std;
ll n, m;

struct DSU{
	int num;
	vector<int> fa, sz, edge;
	DSU(int x) : num(x), fa(x + 1), sz(x + 1, 1), edge(x + 1, 0){
		for(int i = 0; i <= x; ++ i){
			fa[i] = i;
		}
	}
	int size(int x){ return sz[findfa(x)]; }
	int edgesize(int x){ return edge[findfa(x)]; }
	int findfa(int x){
		while(x != fa[x]) x = fa[x] = fa[fa[x]];
		return x;
	}
	bool same(int x, int y){ return findfa(x) == findfa(y); }
	bool merge(int x, int y){
		x = findfa(x); y = findfa(y);
		++ edge[x];
		if(x == y) return false;
		sz[x] += sz[y];
		edge[x] += edge[y];
		fa[y] = x;
		return true;
	}
};

void solve(){
	cin >> n >> m;
	DSU dsu(n);
	for(int i = 0; i < m; ++ i){
		int u, v;
		cin >> u >> v;
		dsu.merge(u, v);
	}
	ll res = 0, ans = 1;
	priority_queue<ll, vector<ll>, greater<ll>>  q;
	map<int, int> vis;
	for(int i = 1; i <= n; ++ i){
		int f = dsu.findfa(i);
		if(!vis.count(f)){
			vis[f] = 1;
			ll size = dsu.sz[f];
			if(size != 1)
				res +=  size * (size - 1) / 2 - dsu.edgesize(f);
			q.push(size);
		}
	}
	int cs = 0;
	if(q.size() != 1){
		while(cs < 2){
			ans *= q.top();
			q.pop();
			++ cs;
		}
	}else ans = 0;
	if(res) cout << res << '\n';
	else cout << ans << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int t = 1;
	// cin >> t;
	while(t --){
		solve();
	}
	return 0;
}

G Spanning Tree

#include<bits/stdc++.h>
#define ll long long

using namespace std;

typedef pair<int, int> pii;

const int maxm = 1e6;
ll mod = 998244353;
ll n;

ll qpow(ll a, ll x){
	a %= mod;
	ll res = 1;
	while(x){
		if(x & 1) res = res * a % mod;
		a = a * a % mod;
		x >>= 1;
	}
	return res;
}

struct DSU{
	int num;
	vector<int> fa, sz;
	DSU(int x) : num(x), fa(x + 1), sz(x + 1, 1){
		for(int i = 0; i <= x; ++ i){
			fa[i] = i;
		}
	}
	int size(int x){ return sz[findfa(x)]; }
	int findfa(int x){
		while(x != fa[x]) x = fa[x] = fa[fa[x]];
		return x;
	}
	bool same(int x, int y){ return findfa(x) == findfa(y); }
	bool merge(int x, int y){
		x = findfa(x); y = findfa(y);
		if(x == y) return false;
		sz[x] += sz[y];
		fa[y] = x;
		return true;
	}
};

void solve(){
	cin >> n;
	vector<pii> s;
	for(int i = 0; i < n - 1; ++ i){
		int u, v;
		cin >> u >> v;
		s.push_back({u, v});
	}
	vector<pii> t;
	vector<int> e[n + 1];
	for(int i = 0; i < n - 1; ++ i){
		int u, v;
		cin >> u >> v;
		e[u].push_back(v);
		e[v].push_back(u);
		t.push_back({u, v});
	}
	DSU dsu(n);
	ll ans = 1;
	bool f = false;
	for(auto &[u, v] : s){
		u = dsu.findfa(u);
		v = dsu.findfa(v);
		ll su = dsu.size(u), sv = dsu.size(v);
		ans = ans * su % mod * sv % mod;
		if(e[u].size() < e[v].size()) swap(u, v);

		int cnt = 0;
		for(auto x : e[v]){
			if(dsu.findfa(x) == u) ++ cnt;
			else e[u].push_back(x);
		}
		if(cnt != 1){
			f = true; break;
		}
		dsu.merge(u, v);
	}
	if(f) cout << "0\n";
	else{
		ans = qpow(ans, mod - 2);
		cout << ans << '\n';
	}
	return ;
}

signed main(){
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int t = 1;
	// cin >> t;
	while(t --){
		solve();
	}
	return 0;
}

J Minimum Manhattan Distance

题意
在圆 C2 上找一点使得它距离圆 C1 上等概率随机一点的期望曼哈顿距离最短,并求出这个期望

思路
期望是一种加权平均
当随机变量 X 取各个可能值是等概率分布的时候,X 的期望值与算术平均值相等

由于具有对称性,最小期望曼哈顿距离就是该点到 C1 圆心的曼哈顿距离
由曼哈顿距离的等高线可以得知,答案点一定在 C2 四个 $45° $ 方向上,再次观察计算可以发现,答案即为 两圆心的曼哈顿距离减去圆 C2 半径的 $\sqrt{2} $ 倍

代码

#include<bits/stdc++.h>
#define ll long long

using namespace std;

void solve(){
	ll a, b, c, d, A, B, C, D;
	cin >> a >> b >> c >> d;
	cin >> A >> B >> C >> D;
	double x, y, xx, yy;
	x = 1.0 * (a + c) / 2.0;
	y = 1.0 * (b + d) / 2.0;
	xx = 1.0 * (A + C) / 2.0;
	yy = 1.0 * (B + D) / 2.0;
	double r2 = sqrt((C - A) * (C - A) + (D - B) * (D - B)) / 2.0;
	double ans = abs(xx - x) + abs(yy - y) - sqrt(2.0) * r2;
	cout << fixed << setprecision(15) << ans << '\n';
	return ;
}

signed main(){
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int t = 1;
	cin >> t;
	while(t --){
		solve();
	}
	return 0;
}

L KaChang!

$O(n) $ 暴力判断每个时间即可

#include<bits/stdc++.h>
#define ll long long

using namespace std;

void solve(){
	ll n, t;
	cin >> n >> t;
	vector<ll> a(n);
	for(int i = 0; i < n; ++ i){
		cin >> a[i];
	}
	ll k = 2;
	for(int i = 0; i < n; ++ i){
		k = max(k, a[i] / t + (a[i] % t != 0));
	}
	cout << k << '\n';
	return ;
}

signed main(){
	int t = 1;
	// cin >> t;
	while(t --){
		solve();
	}
	return 0;
}
posted on 2023-09-17 21:11  Qiansui  阅读(111)  评论(0编辑  收藏  举报