AtCoder_abc334

发布时间 2023-12-26 17:29:39作者: 某谦

AtCoder_abc334

A - Christmas Present

题目描述

输入两个数 \(B,G(B \neq G)\) ,若 \(B\) 大,输出 Bat ,否则输出 Glove

解题思路

Code

// Problem: A - Christmas Present
// Contest: AtCoder - UNIQUE VISION Programming Contest 2023 Christmas (AtCoder Beginner Contest 334)
// URL: https://atcoder.jp/contests/abc334/tasks/abc334_a
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
int a,b;
int main(){
	cin>>a>>b;
	if(a>b)
		cout<<"Bat";
	else
		cout<<"Glove";
	return 0;
}

B - Christmas Trees

题目描述

现在从 \(A\) 点开始,每隔 \(M\) 的长度种一棵树。

即,所有有树的坐标的集合 \(T\)\(T=\{i\,|\,i=km+a,k\in \Z \}\)

请问 \(L\)\(R\) 之间有多少颗树。

解题思路

先将 \(A\) 点作为零点,将整个数轴分成很多以 \(M\) 为长度的区间,两端点的区间编号一减,再根据正负以及端点上是否正好有树加亿点点细节就好了。

Code

// Problem: B - Christmas Trees
// Contest: AtCoder - UNIQUE VISION Programming Contest 2023 Christmas (AtCoder Beginner Contest 334)
// URL: https://atcoder.jp/contests/abc334/tasks/abc334_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,m,l,r;
int main(){
	cin>>a>>m>>l>>r;
	l-=a,r-=a;
	if(l>0)
		cout<<(r/m-l/m+(l%m==0));
	else if(r>0)
		cout<<(r/m+(-l)/m+1);
	else
		cout<<((-l)/m-(-r)/m+((-r)%m==0));
	return 0;
}

C - Socks 2

题目描述

他有 \(N\) 双袜子,其中 \(K\) 双丢了一只, \(K\) 双袜子中剩下的那只颜色为 \(A_i(1 \le i \le K,1\le A_1 < A_2 <\cdots<A_K\le N)\)

由颜色 \(i,j\) 组成的袜子的怪异度为 \(|i-j|\)

请问把所有袜子组合起来后总怪异度最小为多少?(若 \(K\) 为奇数则最后可以剩下一只袜子)。

解题思路

若为偶数,直接计算,若为奇数,预处理一下前后缀和然后统计就好了。

Code

// Problem: C - Socks 2
// Contest: AtCoder - UNIQUE VISION Programming Contest 2023 Christmas (AtCoder Beginner Contest 334)
// URL: https://atcoder.jp/contests/abc334/tasks/abc334_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,k;
int a[200005];
int fsum[200005],bsum[200005];
int ans=INT_MAX;
int main(){
	cin>>n>>k;
	for(int i=1;i<=k;i++)
		cin>>a[i];
	for(int i=2;i<=k;i+=2)
		fsum[i]=fsum[i-2]+a[i]-a[i-1];
	for(int i=k-1;i>=0;i-=2)
		bsum[i]=bsum[i+2]+a[i+1]-a[i];
	if(k%2)
		for(int i=0;i<=k;i+=2)
			ans=min(ans,fsum[i]+bsum[i+2]);
	else
		ans=fsum[k];
	cout<<ans;
	return 0;
}

D - Reindeer and Sleigh

题目描述

\(N\) 个雪橇,其中第 \(i\) 个雪橇需要 \(R_i\) 匹驯鹿来拉。每匹驯鹿最多拉一个雪橇。现有 \(Q\) 次询问,每次询问给你 \(X\) ,问你如果有 \(X\) 匹驯鹿,最多能拉多少个雪橇?

第一行输入 \(N,Q\),第二行输入 \(R_i\),接下来每行输入一个询问。

解题思路

这题放到B都高了。

很简单的前缀和加二分,属于是读完题做不出来就该内啥的程度。

Code

// Problem: D - Reindeer and Sleigh
// Contest: AtCoder - UNIQUE VISION Programming Contest 2023 Christmas (AtCoder Beginner Contest 334)
// URL: https://atcoder.jp/contests/abc334/tasks/abc334_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,q;
ll a[200005];
ll sum[200005];
int main(){
	cin>>n>>q;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++)
		sum[i]=sum[i-1]+a[i];
	for(int i=1;i<=q;i++){
		ll t;cin>>t;
		int p=upper_bound(sum+1,sum+1+n,t)-sum-1;//能用stl谁手写啊
		cout<<p<<endl;
	}
	return 0;
}

E - Christmas Color Grid 1

题目描述

输入一个 \(H\times W\) 的网格,请计算随机将一个 . 变成 # 后, # 的四连通块的期望数量对 \(998244353\) 取模。

解题思路

要不是这题涉及了个乘法逆元[1]和求期望[2]他就应该跟着上面那道题滚去 B 题待着。

可以枚举每一个 . 计算将他变成 # 后的连通块数量然后求期望即可。

Code

// Problem: E - Christmas Color Grid 1
// Contest: AtCoder - UNIQUE VISION Programming Contest 2023 Christmas (AtCoder Beginner Contest 334)
// URL: https://atcoder.jp/contests/abc334/tasks/abc334_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
ll n,m,cnt,cnt2,sum;
ll mp[1003][1003];
int pos[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
void exgcd(ll a,ll b,ll& x,ll& y){//扩展欧几里得算法
	if(b==0){
		x=1,y=0;
		return;
	}
	exgcd(b,a%b,y,x);
	y-=a/b*x;
}
ll mulinv(ll a,ll b){//求乘法逆元
	ll x,y;
	exgcd(a,b,x,y);
	return x;//x即为a在%b时的逆元
}
void dfs(int i,int j,int k){
	mp[i][j]=k;
	for(int l=0;l<4;l++)
		if(mp[i+pos[l][0]][j+pos[l][1]]==-1)
			dfs(i+pos[l][0],j+pos[l][1],k);
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++){
			char t;cin>>t;
			if(t=='#')
				mp[i][j]=-1;//输入处理
		}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(mp[i][j]==-1)
				dfs(i,j,++cnt);//先跑一遍dfs计算连通块,不然每染一次色都跑dfs会T
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(mp[i][j]==0){
				cnt2++;//记录情况的总数
				set <int> st;//利用set内会排除重复值的特性计算这个点周围有几个连通块
				for(int l=0;l<4;l++)
					if(mp[i+pos[l][0]][j+pos[l][1]]!=0)
						st.insert(mp[i+pos[l][0]][j+pos[l][1]]);
				sum+=cnt+1-st.size();
				sum%=mod;
			}
	sum*=mulinv(cnt2,mod);//乘法逆元
	sum=(sum%mod+mod)%mod;
	cout<<sum;
	return 0;
}

  1. 请移步oiwiki 乘法逆元 ↩︎

  2. 对所有可能的结果求平均数 ↩︎