Good Bye 2019E(点坐标缩小一半以区分奇偶性)

设某个点的坐标为(x,y),根据坐标奇偶性公可分为四类,0表示偶数,1表示奇数,(0,0),(0,1),(1,0),(1,1)。

如果所有点的坐标都属于一类,那么它们之间的距离都是4的倍数,无法分辨。

此时将它们的坐标缩小一半,直至区分出奇偶性。

只要有至少一个点的坐标和其他点不在一类里,则可以分为两类。

假设同时存在坐标和为奇数以及坐标和为偶数的点,那么以坐标和为奇数或偶数为标准划分,则两类点在同类中的距离均为4的倍数,而与不同类点的距离是奇数,显然不等,故可行。

如果不能满足上述条件,还可以假设同时存在(0,0)和(1,1)或者同时存在(0,1)和(1,0)的点,那么以横坐标是否为偶数进行划分,则两类点在同类中的距离均为4的倍数,而与不同类点的距离为4的倍数+2(两个奇数相加必定和为2,剩余部分为两个偶数的平方必定为4的倍数),显然距离不等,故可行。

所以关键在于将所有的点都通过缩小的方式把它们分为至少2类。

如果坐标很小的情况下,除以2会将其奇偶性抹去,所以可以先把点的坐标加上初始最大值1e6。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main() {
 4     ios_base::sync_with_stdio(0);
 5     cin.tie(NULL);
 6     cout.tie(NULL);
 7     int n;
 8     cin>>n;
 9     vector<pair<int, int>> p(n);
10     for (int i = 0; i<n; i++) {cin>>p[i].first>>p[i].second; p[i].first+=1e6; p[i].second+=1e6;}
11     while (true){
12         vector<vector<int>> cnt(2, vector<int>(2));
13         for (int i = 0; i<n; i++) cnt[p[i].first%2][p[i].second%2]++;
14         if (cnt[0][0]+cnt[1][1]>0 && cnt[0][1]+cnt[1][0]>0){
15             vector<int> A;
16             for (int i = 0; i<n; i++) if ((p[i].first + p[i].second)%2==0) A.push_back(i);
17             cout<<A.size()<<endl;
18             for (auto it: A) cout<<it+1<<' ';
19             return 0;
20         }
21         if (cnt[0][0]+cnt[0][1]>0 && cnt[1][1]+cnt[1][0]>0){
22             vector<int> A;
23             for (int i = 0; i<n; i++) if (p[i].first%2==0) A.push_back(i);
24             cout<<A.size()<<endl;
25             for (auto it: A) cout<<it+1<<' ';
26             return 0;
27         }
28         int x, y;
29         for (int i = 0; i<2; i++)
30             for (int j = 0; j<2; j++) if (cnt[i][j]>0) {x = i; y = j;}
31         for (int i = 0; i<n; i++) {p[i].first = (p[i].first - x)/2; p[i].second = (p[i].second - y)/2;}
32     }
33 }
 1 #define HAVE_STRUCT_TIMESPEC
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 int a[1007],b[1007];
 5 int ans[1007];
 6 int main(){
 7     ios::sync_with_stdio(false);
 8     cin.tie(NULL);
 9     cout.tie(NULL);
10     int n;
11     cin>>n;
12     for(int i=1;i<=n;++i)
13         cin>>a[i]>>b[i];
14     int cnt=0;
15     while(cnt==0||cnt==n){
16         cnt=0;
17         for(int i=1;i<=n;++i){
18             if((a[i]+b[i])&1)
19                 ans[++cnt]=i;
20             int x=a[i],y=b[i];
21             a[i]=(x+y)>>1;
22             b[i]=(x-y)>>1;
23         }
24     }
25     cout<<cnt<<"
";
26     for(int i=1;i<=cnt;++i)
27         cout<<ans[i]<<" ";
28  
29     return 0;
30 }
保持热爱 不懈努力 不试试看怎么知道会失败呢(划掉) 世上无难事 只要肯放弃(划掉)
原文地址:https://www.cnblogs.com/ldudxy/p/12119856.html