CF Good Bye 2019部分题解

原文发布于我的洛谷博客https://www.luogu.com.cn/blog/why112/cf-good-bye-2019-bu-fen-ti-xie

A Card Game

这个题就是打牌,每次出一张牌,出牌大的把两张都拿走,如果有一个人手里没牌了,另一个人就获胜。如果玩家一赢了输出YES,玩家二赢了输出NO。显然我们只需要看这两个人手中牌中最大值谁的最大。如果是玩家一最大输出YES,否则输出NO

#pragma once
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#include<ext/rope>
#define ll long long
#define rep(i,j,k)	for(int i=j;i<=k;i++)
#define rrep(i,j,k)	for(int i=j;i>=k;i--)
#define mod 1000000007
#define bug printf("-------Bug is here!-------")
#define pii pair<int,int>
#define pic pair<int,char>
#define pcc pair<char,char>
#define pci pair<char,int>
#define pipii pair<int,pair<int,int> >
#define vpii vector<pair<int,int> >
#define mp make_pair
#define pb push_back
using namespace std;
using namespace __gnu_cxx;
int t,n,k1,k2,max1,max2;
int main(){
	//srand(time(NULL));
	ios::sync_with_stdio(false);
	cin>>t;
	while(t--){
		cin>>n>>k1>>k2;
		max1=-1,max2=-1;
		int temp;
		for(int i=0;i<k1;i++){
			cin>>temp;
			if(temp>max1)	max1=temp;
		}
		for(int i=0;i<k2;i++){
			cin>>temp;
			if(temp>max2)	max2=temp;
		}
		if(max1>max2)	cout<<"YES\n";
		else cout<<"NO\n";
	}
	return 0;
}

D Strange Device

这个题的难点在于读题,蒟蒻表示第一次遇到这种交互类的题。。。题目意思是一开始后台有一个数组a,一开始只给出数组a的长度n和k,然后你可以不断对后台提问,格式为:? x1 x2 … xk 也就是说问号后面有k个数,代表下标。然后后台会把这k个位置上的数排序之后返回给第m大的数的位置和值。比如样例中数组a为2 0 1 9,k=3,m=3,如果我们输出? 1 2 3,那么就是2 0 1这三个数排序成0 1 2然后返回2这个数,2在a中的下标是1,所以后台会返回1 2。这个题要求我们猜m的值是多少,询问次数不能超过n次。

显然我们并不需要猜后台的这个数组最终是什么。我们只看前k+1个数。假设我们有个数组a是1 2 3 4 5 6 7 8 9,k=6,m=3。

我们进行如下询问:

? 2 3 4 5 6 7

? 1 3 4 5 6 7

? 1 2 4 5 6 7

? 1 2 3 5 6 7

? 1 2 3 4 6 7

? 1 2 3 4 5 7

? 1 2 3 4 5 6

我们会发现4返回了3次,3返回了4次。也就是说出现的最大的数的出现次数即为m。根据这个规律写代码:

#pragma once
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#include<ext/rope>
#define ll long long
#define rep(i,j,k)	for(int i=j;i<=k;i++)
#define rrep(i,j,k)	for(int i=j;i>=k;i--)
#define mod 1000000007
#define bug printf("-------Bug is here!-------")
#define pii pair<int,int>
#define pic pair<int,char>
#define pcc pair<char,char>
#define pci pair<char,int>
#define pipii pair<int,pair<int,int> >
#define vpii vector<pair<int,int> >
#define mp make_pair
#define pb push_back
using namespace std;
using namespace __gnu_cxx;
int n,m,k,pos,v,ans=-1;
void out(int num){
	cout<<"? ";
	for(int i=1;i<=k+1;i++){
		if(i==num)	continue;
		cout<<i<<" ";
	}
	cout<<endl;
	cout.flush();
}
int main(){
	//srand(time(NULL));
	ios::sync_with_stdio(false);
	cin>>n>>k;
	for(int i=1;i<=k+1;i++){
		out(i);
		cin>>pos>>v;
		if(v>ans){
			m=1;
			ans=v;
		}
		else if(v==ans)	m++;
	}
	cout<<"! "<<m;
	cout.flush(); 
	return 0;
}

E Divide Points

这个题虽然短,读题可能有点懵逼。题意是现在我们给出n个在二维坐标系中的点,然后把这些点分成两组。分完之后我们要保证以下条件:

我们把每两个点之间的距离用颜色标识,如果是同组之间的距离用黄色,否则是蓝色,我们要保证蓝色和黄色的数没有相同的。

我们可以根据奇偶性来划分。我们把坐标分成四类:00 11 01 10 0代表偶数,1代表奇数。

我们发现自身之间点的距离的平方都是偶数,00-11是偶数,10-01是偶数,00-10和00-01是奇数,11-10和11-01也是奇数。当四类都存在时(至少有00或11,以及10或01),00-11一组,10-01一组,保证了黄数都为偶数,蓝数都为奇数。

只存在00-11时,我们发现00和11内部的距离还能被4整除,然而00-11不行,所以00和11各一组。

当然,我们的推理是建立在00存在的基础上。我们可以对坐标进行预处理保证00存在,因为(0,0)便是00类的点,所以我们可以把整个图关于第一个点进行一次平移,然后让第一个点变成(0,0)。当所有的点都是00类时,所有点都除以2,直到出现非00点,然后进行分类然后输出。

#pragma once
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#include<ext/rope>
#define ll long long
#define rep(i,j,k)	for(int i=j;i<=k;i++)
#define rrep(i,j,k)	for(int i=j;i>=k;i--)
#define mod 1000000007
#define bug printf("-------Bug is here!-------")
#define pii pair<int,int>
#define pic pair<int,char>
#define pcc pair<char,char>
#define pci pair<char,int>
#define pipii pair<int,pair<int,int> >
#define vpii vector<pair<int,int> >
#define mp make_pair
#define pb push_back
using namespace std;
using namespace __gnu_cxx;
int n;
pii node[1005];
bool isEven(int num){
	if(num<0)	num=num*(-1);
	if(num%2==0)	return true;
	return false;
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n;
	cin>>node[1].first>>node[1].second;
	for(int i=2;i<=n;i++){
		cin>>node[i].first>>node[i].second;
		node[i].first-=node[1].first;
		node[i].second-=node[1].second;
	}
	node[1].first=0;
	node[1].second=0;
	while(true){
		int a00[1005],a11[1005],a[1005];
		int flag00=0,flag11=0,flag=0;
		for(int i=1;i<=n;i++){
			bool f=isEven(node[i].first),s=isEven(node[i].second);
			if(f&&s)	a00[flag00++]=i;
			else if((!f)&&(!s))	a11[flag11++]=i;
			else a[flag++]=i;
		}
		if(flag00==n){
			for(int i=1;i<=n;i++){
				node[i].first/=2;
				node[i].second/=2;
			}
			continue;
		}
		if(flag==0){
			cout<<flag00<<"\n";
			for(int i=0;i<flag00;i++) cout<<a00[i]<<" ";
		}
		else{
			cout<<flag00+flag11<<"\n";
			for(int i=0;i<flag00;i++) cout<<a00[i]<<" ";
			for(int i=0;i<flag11;i++) cout<<a11[i]<<" ";
		}
		cout<<"\n";
		break;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值