CodeForces 988D Points and Powers of Two
题目
题目大意
有一个 N(1≤N≤2×105) N ( 1 ≤ N ≤ 2 × 10 5 ) 个点的点集,我们要在这个点集中选出尽可能多的点,使任意两点间距离的绝对值是 2 2 的整数次幂。
思路
我们到底最多可以选多少个点呢?我们来推导一下:
1.只有一个点时:点集中没有可以和它作差的点,故此情况成立。
2.有两个点时:只要两点间距离为的整数次幂,就可以成立。
3.有三个点时: 如下图:设
A,B,C
A
,
B
,
C
为满足要求的三点。其中,设
|AC|=2k1,|BC|=2k2,|AC|=2d
|
A
C
|
=
2
k
1
,
|
B
C
|
=
2
k
2
,
|
A
C
|
=
2
d
可得:
2k1+2k2=2d
2
k
1
+
2
k
2
=
2
d
不妨设
k1≤k2
k
1
≤
k
2
则:
1+2k2−k1=2d−k1
1
+
2
k
2
−
k
1
=
2
d
−
k
1
整理可得:
2k2−k1×(2d−k2−1)=1
2
k
2
−
k
1
×
(
2
d
−
k
2
−
1
)
=
1
由题意可知:
k1≥0,k2≥0,d≥0
k
1
≥
0
,
k
2
≥
0
,
d
≥
0
所以:
2k2−k1>0
2
k
2
−
k
1
>
0
且
2d−k2>0
2
d
−
k
2
>
0
所以:
k2−k1=0,d−k2=1
k
2
−
k
1
=
0
,
d
−
k
2
=
1
即:当三点间距离满足最长距离是较短距离的两倍且两较短距离相等时,点集中有三个点。
4.有三个以上的点时:设
A1,A2,A3,A4...Am
A
1
,
A
2
,
A
3
,
A
4
.
.
.
A
m
为满足要求的点。
由上可知,所有三元组:
{A1,A2,A3},{A1,A2,A4},{A1,A3,A4}...
{
A
1
,
A
2
,
A
3
}
,
{
A
1
,
A
2
,
A
4
}
,
{
A
1
,
A
3
,
A
4
}
.
.
.
都需要满足这个条件。
显然这是不可能的。
故此假设不成立。
以此类推,可得:满足条件的点集最多只有 3 3 个。
实现细节
我们可以使用map
标记位于位置的点是否存在于点集中。
正解代码
#include<map>
#include<cstdio>
#include<algorithm>
using namespace std;
const int Maxn=2*1e5;
int N,P[Maxn+5];
map<int,bool> Is_p;
int main() {
#ifdef LOACL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
Init();
scanf("%d",&N);
for(int i=1;i<=N;i++) {
scanf("%d",&P[i]);
Is_p[P[i]]=true;
}
sort(P+1,P+N+1);
for(int i=1;i<=N;i++)
for(int j=0;j<32;j++) {
int x=1<<j;
if(Is_p[P[i]+x]&&Is_p[P[i]+x*2]) {
puts("3");
printf("%d %d %d\n",P[i],P[i]+x,P[i]+x*2);
return 0;
}
}
for(int i=1;i<=N;i++)
for(int j=0;j<32;j++) {
int x=1<<j;
if(Is_p[P[i]+x]) {
puts("2");
printf("%d %d\n",P[i],P[i]+x);
return 0;
}
}
printf("1\n%d\n",P[1]);
return 0;
}