AtCoder Beginner Contest 282 A-F 题解

比赛链接

A - Generalized ABC

额,对,是的,没错,先这样再那样然后这样

就是这样。

#include<cstdio>

int n;

int main() {
	scanf("%d", &n);
	for(int i = 0; i < n; i ++) {
		printf("%c", 'A' + i);
	}
	
	return 0;
} 

B - Let's Get a Perfect Score

枚举所有组合,然后暴力判断就好。

#include<cstdio>
const int N = 35;

char s[N][N];
int n, m, ans;

bool check(int x, int y) {
	for(int i = 1; i <= m; i ++) {
		if(s[x][i] == 'x' && s[y][i] == 'x') return 0;
	}
	return 1;
}

int main() {
	scanf("%d %d", &n, &m);
	for(int i = 1; i <= n; i ++) scanf("%s", s[i] + 1);
	for(int i = 1; i <= n; i ++) {
		for(int j = i + 1; j <= n; j ++) ans += check(i, j);
	}
	printf("%d", ans);
	return 0;
} 

C - String Delimiter

差分,记录一下 封闭区间,然后直接枚举转移就好。


#include<cstdio>
const int N = 2e5 + 5;

char s[N], ans[N];

int n, tot, v[N];

int main() {
	scanf("%d %s", &n, s + 1);
	for(int i = 1; i <= n; i ++) {
		if(s[i] == '"') {
			tot ++;
			if(tot & 1) v[i] ++;
			else v[i] --;
		}
	}
	for(int i = 1; i <= n; i ++) v[i] += v[i - 1];
	
	for(int i = 1; i <= n; i ++) {
		if(s[i] != ',') ans[i] = s[i];
		else if(!v[i]) ans[i] = '.';
		else ans[i] = ',';
	}
	printf("%s", ans + 1);
	return 0;
} 

D - Make Bipartite 2

是哪个大冤种 return 0 写成了 return 1 导致 RE 还没发现, 开开心心去切下一题,然后痛失 400 pts。

哦,是我呀~

首先,二分图内没有长度为奇数的回路。

所以如果我们将一个图内的点分为两部分,这两部分的点互相连起来的不重复的点都满足是二分图的条件。

于是,我们先判断每个联通块是否是二分图,如果不是,答案为 0,

然后记录一下两种颜色的点数 c1 , c2,计算出他们的贡献就好。

关于贡献,无非就是有一个联通分量,或者多个联通分量。

  • 对于一个联通分量,贡献为 c1 * c2 - m

  • 而多个联通分量,其实就是 每个联通分量的可能的连边 c1 * c2 再加上 各个联通分量之间连边 (c1 + c2) * (n - c1 - c2) 再减去本来的连边 m。

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 2e5 + 5;
#define int long long
vector<int> G[N];
int n, m, col[N], cnt1, cnt2;

bool dfs(int x, int c) {
	col[x] = c;
	if(c == 1) cnt1 ++;
	else cnt2 ++;
	int ver;
	for(int i = 0; i < G[x].size(); i ++) {
		ver = G[x][i];
		if(col[ver] == c) return 0;
		if(!col[ver] && !dfs(ver, 3 - c)) return 0; 
	}
	return 1;
}
int ans1, ans2;
signed main() {
	scanf("%lld %lld", &n, &m);
	int u, v;
	for(int i = 1; i <= m; i ++) {
		scanf("%lld %lld", &u, &v);
		G[u].push_back(v), G[v].push_back(u);
	}
	for(int i = 1; i <= n; i ++) {
		if(!col[i]) {
			cnt1 = cnt2 = 0;
			if(!dfs(i, 1)) {
				puts("0");
				return 0;
			}
			ans1 += cnt1 * cnt2;
			ans2 += (cnt1 + cnt2) * (n - cnt1 - cnt2); 
		}
	}
	printf("%lld", ans1 + ans2 / 2 - m);
	return 0;
}

E - Choose Two and Eat One

分析可得,一共会执行 n - 1 次操作,

所以我们可以 \(n^2\) 枚举每个分数,

可以直接建图,跑最大生成树,计算答案。

完了。

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 505;
#define int long long
vector<int> G[N];
bool vis[N];
int n, m, ans, a[N], dis[N], dp[N][N];

int qpow(int a, int b) {
	int res = 1;
	while(b) {
		if(b & 1) res = res * a % m;
		a = a * a % m, b >>= 1;
	}
	return res;
}

void solve() {
	memset(dis, -1, sizeof(dis));
	int tmp;
	for(int i = 0; i < n; i ++) {
		tmp = -1;
		for(int j = 1; j <= n; j ++) {
			if(!vis[j] && (tmp == -1 || dis[tmp] < dis[j])) tmp = j;
		}
		if(i && dis[tmp] == -1) return;
		if(i) ans += dis[tmp];
		vis[tmp] = 1;
		for(int j = 1; j <= n; j ++) dis[j] = max(dis[j], dp[j][tmp]);
	}
}
signed main() {
	
	scanf("%lld %lld", &n, &m);
	for(int i = 1; i <= n; i ++) scanf("%lld", &a[i]);
	
	for(int i = 1; i <= n; i ++) {
		for(int j = 1; j <= n; j ++) {
			if(i == j) dp[i][j] = -1;
			else dp[i][j] = (qpow(a[i], a[j]) + qpow(a[j], a[i])) % m;
		}
	}
	solve();
	
	printf("%lld", ans);
	return 0;
}

F - Union of Two Sets

不会写交互题,

(摆烂姿态)

posted @ 2023-02-25 11:28  Spring-Araki  阅读(15)  评论(0编辑  收藏  举报