(Atcoder Beginner Contest 348)题解

前言

这是我第 4 4 4 次做出 F F F 题,庆祝上蓝!
在这里插入图片描述

正题

本题解提供 A − F A-F AF 题题解,欢迎诸位大佬参考。

第 1 题 Penalty Kick

照例很水,模拟即可。

#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main(){
	int n; cin>>n;
	for (int i=1; i<=n; i++){
		if (i%3==0) cout<<"x";
		else cout<<"o";
	}
	return 0;
} 

第 2 题 Farthest Point

也是很简单,枚举即可。注意为了 不丢失精度,我们用到了显而易见的定理:
如果:
x 2 > y 2 x^2>y^2 x2>y2

那么:
x > y x>y x>y

#include <bits/stdc++.h>
using namespace std;
#define int long long
int x[110],y[110];
signed main(){
	int n; cin>>n;
	for (int i=1; i<=n; i++){
		cin>>x[i]>>y[i];
	}for (int i=1; i<=n; i++){
		int mx=0; int id;
		for (int j=1; j<=n; j++){
			int dis=(x[j]-x[i])*(x[j]-x[i])+(y[j]-y[i])*(y[j]-y[i]);
			if (dis>mx) mx=dis,id=j; 
		}cout<<id<<"\n";
	}
	return 0;
} 

第 3 题 Colorful Beans

需要使用到 m a p map map 容器,不知诸位大佬是否知道。
这里不太方便讲述,就找了一篇:map 使用方法-优快云

#include <bits/stdc++.h>
using namespace std;
#define int long long
map <int,int> mp;
signed main(){
	int n; cin>>n;
	for (int i=1; i<=n; i++){
		int u,v; cin>>v>>u; 
		if (!mp[u]) mp[u]=v;
		else mp[u]=min(mp[u],v);
	}int mx=0;
	for (auto x:mp) mx=max(mx,x.second);
	cout<<mx;
	return 0;
} 

第 4 题 Medicines on Grid

注意,题中的药物只会让你的能量值 变为 某个值,而 不是增加

那么我们可以注意到,我们把药物也变成图,两个药物 a , b a,b a,b 有边,仅当 a a a 处吃药后可以不使用任何药物走到 b b b。我们可以在 a a a b f s bfs bfs,查看是否可以在药物作用内走到 b b b

有了这个定义,我们可以求解问题了!假设我们的起点处的药物叫 S S S,作用范围 0 0 0,终点处是 T T T,作用范围是 0 0 0,那么我们可以在图上再跑 b f s bfs bfs,查看 S S S 是否可以走到 T T T

#include <bits/stdc++.h>
using namespace std;
#define int long long
int mx[4]={0,0,-1,1};
int my[4]={-1,1,0,0};
bool vis[310][310];
string mp[310];
int id[310][310],n,m,k;
vector <int> vc[310];
int x[310],y[310],e[310],ans[310];
void dfs(int x,int y,int ma){
	queue <int> qx,qy,qz;
	qx.push(x); qy.push(y); qz.push(0);
	while (qx.size()){
		int x=qx.front(); qx.pop();
		int y=qy.front(); qy.pop();
		int z=qz.front(); qz.pop();
		if (z==ma) continue; 
		for (int i=0; i<4; i++){
			int nx=x+mx[i];
			int ny=y+my[i];
			if (nx<1||ny<1||nx>n||ny>m) continue;
			if (vis[nx][ny]||mp[nx][ny]=='#') continue;
			qx.push(nx); qy.push(ny); qz.push(z+1);
			vis[nx][ny]=1;
		} 
	}
}void solve(int x){
	for (auto u:vc[x]){
		if (!ans[u]){
			ans[u]=1; solve(u);
		}
	}
}signed main(){
	cin>>n>>m;
	for (int i=1; i<=n; i++){
		cin>>mp[i]; mp[i]=" "+mp[i];
	}cin>>k; int s,t;
	for (int i=1; i<=k; i++){
		cin>>x[i]>>y[i]>>e[i];
		id[x[i]][y[i]]=i;
	}for (int i=1; i<=n; i++){
		for (int j=1; j<=m; j++){
			if (mp[i][j]=='S') s=id[i][j];
			if (mp[i][j]=='T'){
				if (id[i][j]) t=id[i][j];
				else k++,t=k,id[i][j]=k,x[k]=i,y[k]=j,e[k]=0;
			}
		}
	}for (int i=1; i<=k; i++){
		memset(vis,0,sizeof(vis));
		vis[x[i]][y[i]]=1;
		dfs(x[i],y[i],e[i]);
		for (int j=1; j<=n; j++){
			for (int k=1; k<=m; k++){
				if (vis[j][k]&&id[j][k]){
					vc[i].push_back(id[j][k]);
				}
			}
		}
	}ans[s]=1; solve(s);
	cout<<(ans[t]?"Yes":"No");
	return 0;
} 

第 5 题 Minimize Sum of Distances

这道题看似很难,但这里介绍一种方法:换根 D P DP DP

假设现在有一棵树(如下图),它的根是 u u u,我们要把根换到 v v v,求权值(每个点的深度乘点权和)变化。

在这里插入图片描述

那么可以发现,它增长了黑色权值和减红色权值和。黑色好算,是 v v v 的子树,红色可以用总权值减黑色计算。

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m,a[2010][2010];
bitset <2010> s[1010],ans[2010];
vector <int> vc[1010];
signed main(){
	cin>>n>>m;
	for (int i=1; i<=n; i++){
		for (int j=1; j<=m; j++){
			cin>>a[i][j];
		}
	}for (int j=1; j<=m; j++){
		memset(s,0,sizeof(s)); 
		for (int i=1; i<1000; i++) vc[i].clear();
		for (int i=1; i<=n; i++){
			s[a[i][j]][i]=1; vc[a[i][j]].push_back(i);
		}for (int i=1; i<1000; i++){
			for (auto x:vc[i]){
				ans[x]^=s[i];
			}
		}
	}int cnt=0;
	for (int i=1; i<=n; i++){
		for (int j=i+1; j<=n; j++){
			if (ans[i][j]) cnt++;
		}
	}cout<<cnt;
	return 0;
} 

第 6 题 Oddly Similar

看似不好做的一道难题,正所谓:

智商不够,数据结构来凑。

这道题用到的是 b o o l bool bool 类型数据结构,那非 b i t s e t bitset bitset 莫属啦!

B i t s e t Bitset Bitset 是一种自带容器,它可以存储一个 01 01 01 数组,可以支持位运算,速度加快 64 64 64
这里介绍一下用法。

  1. & 与运算,通常用于所有条件都成立才可以的决策。
  2. | 或运算,通常用于满足一个条件即可的决策,如背包问题
  3. ^ 异或运算,通常运用在 奇偶问题 中。
  4. << >> 移位运算,通常配合使用前面的所有运算。

本题只会用到 ^,其它的自行了解。本题的解法可以使用 n n n n n n 位的 b i t s e t bitset bitset,表示它们每行的关系。

如果我们枚举每一列,然后把所有一样的数归在一起,那么就可以把桶数字任意一个数异或上这个序列对应的 b i t s e t bitset bitset 1 1 1 0 0 0 无)。

那么这时 ( i , j ) (i,j) (i,j) 的值为 1 1 1,证明它们之间有奇数个不同的数位。复杂度 O ( n 2 m 64 ) O(\frac{n^2m}{64}) O(64n2m),可以通过。

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m,a[2010][2010];
bitset <2010> s[1010],ans[2010];
vector <int> vc[1010];
signed main(){
	cin>>n>>m;
	for (int i=1; i<=n; i++){
		for (int j=1; j<=m; j++){
			cin>>a[i][j];
		}
	}for (int j=1; j<=m; j++){
		memset(s,0,sizeof(s)); 
		for (int i=1; i<1000; i++) vc[i].clear();
		for (int i=1; i<=n; i++){
			s[a[i][j]][i]=1; vc[a[i][j]].push_back(i);
		}for (int i=1; i<1000; i++){
			for (auto x:vc[i]){
				ans[x]^=s[i];
			}
		}
	}int cnt=0;
	for (int i=1; i<=n; i++){
		for (int j=i+1; j<=n; j++){
			if (ans[i][j]) cnt++;
		}
	}cout<<cnt;
	return 0;
} 
AtCoder Beginner Contest 134 是一场 AtCoder 的入门级比赛,以下是每道题的简要题解: A - Dodecagon 题目描述:已知一个正十二边形的边长,求它的面积。 解题思路:正十二边形的内角为 $150^\circ$,因此可以将正十二边形拆分为 12 个等腰三角形,通过三角形面积公式计算面积即可。 B - Golden Apple 题目描述:有 $N$ 个苹果和 $D$ 个盘子,每个盘子最多可以装下 $2D+1$ 个苹果,求最少需要多少个盘子才能装下所有的苹果。 解题思路:每个盘子最多可以装下 $2D+1$ 个苹果,因此可以将苹果平均分配到每个盘子中,可以得到最少需要 $\lceil \frac{N}{2D+1} \rceil$ 个盘子。 C - Exception Handling 题目描述:给定一个长度为 $N$ 的整数序列 $a$,求除了第 $i$ 个数以外的最大值。 解题思路:可以使用两个变量 $m_1$ 和 $m_2$ 分别记录最大值和次大值。遍历整个序列,当当前数不是第 $i$ 个数时,更新最大值和次大值。因此,最后的结果应该是 $m_1$ 或 $m_2$ 中较小的一个。 D - Preparing Boxes 题目描述:有 $N$ 个盒子和 $M$ 个物品,第 $i$ 个盒子可以放入 $a_i$ 个物品,每个物品只能放在一个盒子中。现在需要将所有的物品放入盒子中,每次操作可以将一个盒子内的物品全部取出并分配到其他盒子中,求最少需要多少次操作才能完成任务。 解题思路:首先可以计算出所有盒子中物品的总数 $S$,然后判断是否存在一个盒子的物品数量大于 $\lceil \frac{S}{2} \rceil$,如果存在,则无法完成任务。否则,可以用贪心的思想,每次从物品数量最多的盒子中取出一个物品,放入物品数量最少的盒子中。因为每次操作都会使得物品数量最多的盒子的物品数量减少,而物品数量最少的盒子的物品数量不变或增加,因此这种贪心策略可以保证最少需要的操作次数最小。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值