原文发布于我的洛谷博客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;
}