Codeforces-Good Bye 2019 - E
题意:
我们A集合中任意两个点的距离+B集合中任意两个点的距离,这些距离构成集合P。我们在A,B集合中各选一个点,将他们形成的所有距离构成集合Q。
题解:
我们直接计算如果x,y的坐标和为偶数的个数不等于0且不等于n的话,那么我们一定能构造成 A 11 , A 00 为 一 个 点 集 合 , A 01 A 10 为 另 一 个 点 集 A_{11},A_{00}为一个点集合,A_{01}A_{10}为另一个点集 A11,A00为一个点集合,A01A10为另一个点集,(下标为0则是偶数,1是奇数),那么我们在这两个点集合中,同一个集合中的距离一定为偶数,不同集合中的两两距离一定为奇数,所以满足划分。如果我们并不能找到这样的集合则我们先找一个点当成(0,0)原点,则我们通过切比雪夫距离转曼哈顿距离一直缩小比例,直到找到为止。
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+7;
struct Node{
int x,y;
}p[N];
int main()
{
int n; cin>>n;
for(int i=1;i<=n;i++){
scanf("%d%d",&p[i].x,&p[i].y);
}
while(1){
int cnt=0;
for(int i=1;i<=n;i++) if((p[i].x+p[i].y)%2==0) cnt++;
// cout<<"---"<<endl;
if(cnt!=n&&cnt!=0){
cout<<cnt<<endl;
for(int i=1;i<=n;i++){
if((p[i].x+p[i].y)%2==0){
printf("%d ",i);
}
}
return 0;
}
else{
if((p[1].x+p[1].y)%2==0)
for(int i=1;i<=n;i++){
int x=p[i].x,y=p[i].y;
p[i].x=(x+y)/2;
p[i].y=(x-y)/2;
}
else{
for(int i=1;i<=n;i++){
int x=p[i].x,y=p[i].y;
p[i].x=(x+y+1)/2;
p[i].y=(x-y+1)/2;
}
}
}
}
}
方法二:
前排模一下成都全能王OTZ!!
言归正传
我们以最后一个点为原点重新建立直角坐标系,然后我们再gcd一下,这个时候就有两种情况。
一种是存在
A
01
和
A
10
A_{01}和A_{10}
A01和A10这种数字(看法一对
A
01
A_{01}
A01他们的解释),那么们直接把
A
01
A
10
放
一
个
集
合
A
11
A
00
放
一
个
集
合
A_{01}A_{10}放一个集合A_{11}A_{00}放一个集合
A01A10放一个集合A11A00放一个集合。
另一种是没有
A
01
和
A
10
,
那
我
们
直
接
把
A
11
和
A
00
分
成
两
个
集
合
就
可
以
了
。
A_{01}和A_{10},那我们直接把A_{11}和A_{00}分成两个集合就可以了。
A01和A10,那我们直接把A11和A00分成两个集合就可以了。
因为可能所有数字都是偶数,所以gcd可以把2的倍数都干掉。
#include <bits/stdc++.h>
using namespace std;
const int N=1e3+7;
vector<int>x;
vector<int>y;
vector<int>v;
int main() {
std::ios::sync_with_stdio(false); std::cin.tie(0);
int n;
cin >> n;
for (int i = 0; i < n; ++i) {
int tmp; cin>>tmp; x.push_back(tmp);
cin>>tmp; y.push_back(tmp);
}
int d = 0;
// cout<<x.front()<<y.front()<<endl;
for (int i = 0; i < n; ++i) {
x[i] -= x.back();
y[i] -= y.back();
// cout<<"x : "<<x[i]<<" back :"<<x.back()<<endl;
// cout<<"y : "<<y[i]<<" back :"<<y.back()<<endl;
d = __gcd(d, abs(x[i]));
d = __gcd(d, abs(y[i]));
}
for (int i = 0; i < n; ++i) {
x[i] /= d;
y[i] /= d;
if ((x[i] + y[i] + 1) % 2 == 0) v.push_back(i);
}
if (v.empty()) {
for (int i = 0; i < n; ++i) {
if (x[i] % 2 && y[i] % 2) v.push_back(i);
}
}
cout << v.size() << endl;
for (int i : v) cout << i + 1 << ' ';
return 0;
}