AtCoder_abc337

AtCoder_abc337

A - Scoreboard

简单求和,会写循环就能做,直接贴代码了。

// Problem: A - Scoreboard
// Contest: AtCoder - Toyota Programming Contest 2024#1(AtCoder Beginner Contest 337)
// URL: https://atcoder.jp/contests/abc337/tasks/abc337_a
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
int n,sum1,sum2;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		int x,y;cin>>x>>y;
		sum1+=x;
		sum2+=y;
	}
	if(sum1>sum2)cout<<"Takahashi";
	else if(sum1<sum2)cout<<"Aoki";
	else cout<<"Draw";
	return 0;
}

B - Extended ABC

题目翻译

给出一个字符串 \(S\),请判断 \(S\) 是否是以若干个 A+ 若干个B+ 若干个C 组成(可以为 \(0\) 个)。

解题思路

其实就是要求后面一个字符的 ASCLL 码必须大于等于前面的,如果直接枚举每一种情况判断,那么要记得,AC 这个串也是合理的。

Code

// Problem: B - Extended ABC
// Contest: AtCoder - Toyota Programming Contest 2024#1(AtCoder Beginner Contest 337)
// URL: https://atcoder.jp/contests/abc337/tasks/abc337_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
string s;
int main(){
	cin>>s;
	int n=s.size();
	s=" "+s;
	for(int i=2;i<=n;i++){
		if(s[i]>=s[i-1])
			continue;
		else{
			cout<<"No";
			return 0;
		}
	}
	cout<<"Yes";
	return 0;
}

C - Lining Up 2

题目翻译

现在有一些人正在排队,其中,第 \(i\) 个人站在 \(a_i\) 背后。特别的,若 \(a_i=0\) 则表示 \(i\) 为队首。请按排队顺序输出这 \(i\) 个人的编号。

解题思路

代码甚至比 B 简单,类似链式前向星倒边的操作。

Code

// Problem: C - Lining Up 2
// Contest: AtCoder - Toyota Programming Contest 2024#1(AtCoder Beginner Contest 337)
// URL: https://atcoder.jp/contests/abc337/tasks/abc337_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
int n,bh[300005],s;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		int t;cin>>t;
		if(t==-1)s=i;
		else bh[t]=i;
	}
	for(int i=s;i!=0;i=bh[i])
		cout<<i<<" ";
	return 0;
}

D - 没做出来

E - Bad Juice

题目翻译

这是一道交互题!

这里有 \(N\) 瓶饮料,其中一瓶被下了毒,只要喝一小口这种毒饮料,就会肚子不舒服。

你必须尽快判断到底是哪一瓶被下了毒。为此,你需要叫来最少的朋友,并为他们提供 \(N\) 瓶饮料中的一些。他可以给每个朋友任意瓶饮料,每瓶饮料可以给任意数量的朋友。

请输出要叫来朋友的数量以及如何分发饮料,然后收到每个朋友是否肚子不舒服的信息,最后请输出哪瓶饮料被下了毒。

输入输出格式

在开始之前,评测机选择一个介于 \(1\sim N\) 之间的整数 \(X\) 作为被下毒瓶子的编号。\(X\) 的值不会给出。

首先,评测机会输入一个 \(N\)

然后,你需要输出要叫来朋友的数量 \(M\) 并换行。

接下来 \(M\) 行,请先输出一个 \(K_i\),表示要给第 \(i\) 位朋友喝 \(K_i\) 瓶饮料。下面 \(K_i\) 个数(\(A_{i,1},A_{i,2},\cdots,A_{i,K_i}\))表示要给第 \(i\) 位朋友喝的饮料的编号。

在此之后,评测机会输入一个由 01 组成的长度为 \(M\) 的字符串 \(S\),当且仅当 \(S_i=1\) 时,第 \(i\) 位朋友肚子不舒服。

最后的最后,你需要输出一个数 \(X'\) 并换行,然后立即结束程序。

当且仅当 \(X'=X\)\(M\) 的值最小时,你的输出被认为是正确的。

解题思路

经典老题!

我们可以先将饮料的编号转化成二进制,需要朋友的数量就是 \(N\) 在二进制中的位数。

为什么是二进制呐?因为每位朋友是否拉肚子这个信息只有 \(1\)\(0\) 两种情况,本质就是二进制。

对于朋友 \(i\),我们都让他喝在二进制中,编号第 \(i\) 位为 \(1\) 的饮料。

这样如果第 \(i\) 位朋友拉了肚子,我们就知道被下了毒的饮料第 \(i\) 位为 \(1\)

然后就会喜提 WA*9(赛时就卡死在这里了 QWQ)。

我们考虑如果 \(N\) 是二的整数次幂,那么饮料 \(N\) 会且仅会被第 \(M\) 位朋友喝,第 \(M\) 位朋友喝且仅喝饮料 \(N\)

在这种情况下,我们就可以少叫一位朋友,并且让饮料 \(N\) 不被任何人喝。

这样如果所有朋友都不拉肚子,被下毒的就是饮料 \(N\) 了。

Code

// Problem: E - Bad Juice
// Contest: AtCoder - Toyota Programming Contest 2024#1(AtCoder Beginner Contest 337)
// URL: https://atcoder.jp/contests/abc337/tasks/abc337_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms

#include<bits/stdc++.h>
using namespace std;
int n,m;
vector <int> frd[1000];
int hibit(int x){
	int ret=1,t=x & (-x);
	while(x!=t){
		x-=t;
		t=x & (-x);
	}
	for(int i=1;;i<<=1){
		if(i==x)return ret;
		ret++;
	}
}
int lowbits(int x){
	return x & (-x);
}
int lowbit(int x){
	int t = x & (-x);
	if(t==1)return 1;
	for(int i=1;;i++)
		if((t>>i)==0)return i;
}
int main(){
	cin>>n;
	m=hibit(n);
	if(lowbits(n)==n)
		m--;
	cout<<m<<endl;
	for(int i=1;i<=n-(lowbits(n)==n);i++){
		int t=i;
		while(t){
			frd[lowbit(t)].push_back(i);
			t-=lowbits(t);
		}
	}
	for(int i=1;i<=m;i++){
		cout<<frd[i].size()<<" ";
		int l=frd[i].size();
		for(int j=0;j<l;j++)
			cout<<frd[i][j]<<" ";
		cout<<endl;
	}
	string s;cin>>s;s=" "+s;
	if(lowbits(n)==n){
		bool flag=1;
		for(int i=1;i<s.size();i++)
			if(s[i]=='1'){
				flag=0;break;
			}
		if(flag){
			cout<<n<<endl;
			return 0;
		}
	}
	int ans=0;
	for(int i=1;i<=m;i++){
		if(s[i]=='1')
			ans+=(1<<i)/2;
	}
	cout<<ans<<endl;
	return 0;
}
posted @ 2024-01-21 10:21  某谦  阅读(77)  评论(0编辑  收藏  举报