2020 KAIST 10th ICPC Mock Contest (XXI Open Cup. Grand Prix of Korea. Division 2) 补题 | 题解

2021.2.10 校队训练纪念戳
诶诶诶怎么大年二十九还训练啊qwq
不得不说 感觉这套题好难读题啊qwq 因为我英语太差了qwq??
慢速补题中qwq

A- Advertisement Matching

B- Bombs In My Deck

比较签到的一个题,直接用一个搜索就完事了。
但是注意30的阶乘是大于long long范围的!
实测:20!还在long long范围内,但是21!就超过了qwq

#include<bits/stdc++.h>
using namespace std;
double ans1, ans2;
inline void solve(double x, int a, int b, int c){
   
	if(a <= 0) return;
	double cur_ans = x * b / a;
	if(b > 0) {
   
		if(c <= 5) ans1 += cur_ans;
		else solve(cur_ans, a - 1, b - 1, c - 5);
	}
	return;
}
int main(){
   
	#ifndef ONLINE_JUDGE
	freopen("ce.in", "r", stdin);
	#endif
	int a, b, c;
	scanf("%d%d%d", &a, &b, &c);
	ans2 = 1.0;
	for(int i = 2; i <= a; i++) ans2 *= i; 
	solve(ans2, a, b, c);
	printf("%.7lf\n", (ans2 - ans1) / ans2);
	return 0;
}

C- Economic One-way Roads

D- Fix Wiring

题目大意:有n个点,连一张完全图。现在有n*(n-1)/2个值,你需要由某种策略给每条边赋上这些值,使得建立一个最小生成树的费用最小 和 最大(两问),求最小值和最大值是多少。
最小值显然就是选前n-1条最小的边。
最大值就是我们需要使得小的边尽可能没用。那么我们假设最小生成树应当是从点1连点2,点2连点3…点n-1连点n,我们每次按次序往里面加一个点。
我们可以发现,每次加入一个点的时候,总要向前n-1个点连边。而此时,举个例子来说,如果点i连上了通往点1的边,那么点1到点i这条中间按着顺序直接连的i-1条边中有可能就有一条边不再是最小生成树上的边。
那么我们就有做题策略了,将边从小到大排序之后进行使用。按照次序加点,每次点i向前连边,一直连到通往点1的边(这样是保证i到i-1的边是最小边以使其一定在最小生成树上)。

#include<bits/stdc++.h>
#define MAXN 200010
using namespace std;
int n, m;
int a[MAXN];
long long ans1, ans2;
int main(){
   
	#ifndef ONLINE_JUDGE
	freopen("ce.in", "r", stdin);
	#endif
	scanf("%d", &n);
	m = n * (n - 1) / 2;
	for(int i = 1; i <= m; i++) scanf("%d", &a[i]);
	sort(&a[1], &a[m + 1]);
	for(int i = 1; i <= n - 1; i++) ans1 += a[i];
	int cnt = 0;
	for(int i = 2; i <= n; i++){
   
		for(int j = i - 1; j >= 1; j--){
   
			cnt++;
			if(i == j + 1) ans2 += a[cnt];
		}
	} 
	printf("%lld %lld\n", ans1, ans2);
	return 0;
} 

E- Min-hashing

每个点的l都是不同的,所以在每一个联通块里都是最小值尽可能多的往外传。
如果当前联通块最小值ai在i点,那么对于一个点j来说,它第一次变成ai是在第dis(i,j)次,在这一次之后再传偶数次可以保证它的值还是ai,但是奇数次就不一定是。
所以在k次之后,如果原图是一个二分图的话,就会分成两类,一类是奇数次能够传到,一类是偶数次能被传到。我们对于两类分别计数。
如果不是的话,那么就有至少一条边可以做到奇偶互换,所以无数多次之后整个联通块都会变成一样的最小值。我们对联通块内所有节点进行计数。

#include<bits/stdc++.h>
#define MAXN 300010
#define MAXM 500010
using namespace std;

int n, m, t;
int a[MAXN], head[MAXN], color[MAXN];
long long ans;
long long cnt[3];

struct Edge{
   int nxt, to;}edge[MAXM << 1];

inline void add(int from, int to){
   
	edge[++t].nxt = head[from], edge[t].to = to;
	head[from] = t;
}

inline bool solve(int x, int tmp){
   
	bool flag = true;
	color[x] = tmp;
	cnt[tmp]++;
	for(int i = head[x]; i; i = edge
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值