AtCoder Beginner Contest 282)

比赛链接

A

// Problem: A - Generalized ABC
// Contest: AtCoder - HHKB Programming Contest 2022 Winter(AtCoder Beginner Contest 282)
// URL: https://atcoder.jp/contests/abc282/tasks/abc282_a
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define NO {puts("NO") ; return ;}
#define YES {puts("YES") ; return ;}
#define endl "\n"
#define int long long 


signed main()
{
int k;
cin>>k;
for(int i=0;i<k;i++)
{
	char b='A';
	printf("%c",b+i);
}
}

B

// Problem: B - Let's Get a Perfect Score
// Contest: AtCoder - HHKB Programming Contest 2022 Winter(AtCoder Beginner Contest 282)
// URL: https://atcoder.jp/contests/abc282/tasks/abc282_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define NO {puts("NO") ; return ;}
#define YES {puts("YES") ; return ;}
#define endl "\n"
#define int long long 
const int N=1e3+10;
int a[N][N];

signed main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
	char c;
	cin>>c;
	if(c=='o')
	a[i][j]=1;
}
int ans=0;
for(int i=0;i<n;i++)
{
	for(int j=i+1;j<m;j++)
	{
		int flag=1;
		for(int k=0;k<m;k++)
		{
			if((a[i][k]|a[j][k])==0)
			{
				flag=0;
				break;
			}
		}
		if(flag)
		ans++;
	}
}
cout<<ans<<endl;
}

C

// Problem: C - String Delimiter
// Contest: AtCoder - HHKB Programming Contest 2022 Winter(AtCoder Beginner Contest 282)
// URL: https://atcoder.jp/contests/abc282/tasks/abc282_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define NO {puts("NO") ; return ;}
#define YES {puts("YES") ; return ;}
#define endl "\n"
#define int long long 
const int N = 1e6 + 10;
char s[N];
signed main()
{
	int n;
	cin >> n;
	scanf("%s", &s);
	for (int i = 0;i < n;i++)
	{
		if (s[i] == '"')
		{
			i++;
			while (s[i] != '"')
				i++;
		}
		else if (s[i] == ',')
			s[i] = '.';
	}
	printf("%s", s);
}

D

核心思路

首先普及一个二分图的知识,二分图必须得是一个连通块。

然后这个题目其实只是让我们连一条边,然后求连哪一条边可以使其构成一个二分图。首先我们使用染色法先把这些点全都染色,然后统计黑色(0)和白色(1)的个数。注意我们这是一个联通块一个连通块的统计。

然后就是经典的正难则反的思想了,我们先计算出来这些点所能构成的所有的边数也就是\(n(n-1)/2\).然后删去相同颜色的边:\(cnt[0](cnt[0]-1)/2,cnt[1](cnt[1]-1)/2\).千万别忘了还得减去我们自身的边m.

// Problem: D - Make Bipartite 2
// Contest: AtCoder - HHKB Programming Contest 2022 Winter(AtCoder Beginner Contest 282)
// URL: https://atcoder.jp/contests/abc282/tasks/abc282_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define NO {puts("NO") ; return ;}
#define YES {puts("YES") ; return ;}
#define endl "\n"
#define int long long 
const int N=3e5+10;
vector<int> g[N];
int col[N],cnt[N];
void dfs(int u){
	cnt[col[u]]++;
	for(int &v:g[u]){
		if(col[v]!=-1&&col[v]==col[u]){  
			cout<<0<<endl;  //判断是否为二分图
			exit(0);
		}
		if(col[v]!=-1)continue;
		col[v]=1-col[u];
		dfs(v);
	}
}
 

signed main()
{
	int n,m;
cin>>n>>m;
	for(int i=1;i<=m;i++){
		int a,b;
		cin>>a>>b;
		g[a].push_back(b);
		g[b].push_back(a);
	}
	
	memset(col,-1,sizeof col);
 
	int res=n*(n-1)/2;	 //总边数
	for(int i=1;i<=n;i++)
		if(col[i]==-1){    //统计每个连通块
			cnt[0]=cnt[1]=0;
			col[i]=0;      //初始点染为0
			dfs(i);
			res-=cnt[0]*(cnt[0]-1)/2;  //减去相同颜色的点
			res-=cnt[1]*(cnt[1]-1)/2;  //之间的边
		}
		
	res-=m;   //减去原来的m条边
	cout<<res<<endl;
return 0;
}

e

核心思路

这个题目咋一看是一个数论的题目,其实是一个图论题目。我们只需要把题目要求我们算的条件看成边的权值就是一个图论题目.因为题目要我们每次算完一个之后,要把其中一个球吃掉其实就是沿着这条边往下走。

然后经过这么转换就变成了一个最大生成树问题。这题我们采用Kruscal算法。

Kruascal算法是什么呢,其实就是把我们的边权排序然后再一个一个把那个点合并了。最后就合成了我们想要的最小或者最大生成树,这里的最小和最大取决于我们的排序方式。

// Problem: E - Choose Two and Eat One
// Contest: AtCoder - HHKB Programming Contest 2022 Winter(AtCoder Beginner Contest 282)
// URL: https://atcoder.jp/contests/abc282/tasks/abc282_e
// Memory Limit: 1024 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define NO {puts("NO") ; return ;}
#define YES {puts("YES") ; return ;}
#define endl "\n"
#define int long long 
const int N = 3e3 + 10;
int n, m;

int a[N], p[N];
struct node {
	int a, b, w;
}s[N * N];
int cmp(node a, node b)
{
	return a.w > b.w;
}

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

int find(int x)
{
	if (x != p[x])
		p[x] = find(p[x]);
	return p[x];
}
void solve()
{
	cin >> n >> m;
	for (int i = 1;i <= n;i++)
		cin >> a[i], p[i] = i;
	int cnt = 0;
	for (int i = 1;i <= n;i++)
	{
		for (int j = i + 1;j <= n;j++)
		{
			s[++cnt] = { i,j,(qmi(a[i],a[j]) + qmi(a[j],a[i])) % m };
		}

	}
	sort(s + 1, s + cnt + 1, cmp);
	int res = 0;
	for (int i = 1;i <= cnt;i++)
	{
		int a = s[i].a;
		int b = s[i].b;
		int w = s[i].w;
		if (find(a) != find(b))
		{
			p[find(a)] = find(b);
			res += w;

		}
	
	}
	cout<<res<<endl;
	return;
}


	signed main()
	{
		solve();
	}
posted @ 2023-01-13 19:59  努力的德华  阅读(59)  评论(0)    收藏  举报