题目链接:http://codeforces.com/contest/988/problem/D
题目分析 : 给你一个大小为n的数列,问你最多能够在这个这n个数中选取多少个,使得由他们组成的集合中,两两之间的差的绝对值为2的幂。
题目建模:
这个题最大的难点,在于分析出:这个n<=3;简单证明一下
当n==1||n==2,结论肯定成立
当n==3时
三个数从小到大分别为a,b,c,即要符合条件,则需要满足:
(1)
(2)
(3)
将(2)+(1)可得 ,再根据(3)可得
因为我们知道,要满足题意,x,y,z都必须为2的幂。而要使得2^a1+2^b1==2^c1成立,则不难得出,当且仅当a1==b1时成立,即x==y时成立,此时,不难发现,a,b,c三个数是形成一个等差数列的。
而当集合的大小>=4时,设大小为4,四个数由大到小分别为a,b,c,d。则根据上面的证明,则我们要满足答案,则需要abc、abd、acd、bcd......所有的三元组都需要满足上述式子。显然这是不成立的,因此,大小大于3的答案是不合理的。
证明出来了这个结论,只需要考虑三个以内的答案即可,我们只需要利用等差数列的性质即可
将所有的数存入到 set 中
从第一个数开始枚举,枚举1到1e9中2的幂j,判断a+j和a+2*j是否在set内出现过就行
倘若都不在set内,则随便输出一个数即可。
//注意一下,1也算是在2的幂里面
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<set>
using namespace std;
typedef long long ll;
set<ll>s;
int a[200010];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
s.insert(a[i]);
}
for(int i=0;i<n;i++)
for(ll j=1;j<=2e9;j<<=1)
{
if(s.count(a[i]+j)&&s.count(a[i]+2*j))
{
printf("3\n");
printf("%d %d ",a[i],a[i]+j);
printf("%d\n",a[i]+2*j);
return 0;
}
}
for(int i=0;i<n;i++)
for(ll j=1;j<=2e9;j<<=1)
{
if(s.count(a[i]+j))
{
printf("2\n");
printf("%d %d\n",a[i],a[i]+j);
return 0;
}
}
printf("1\n");
printf("%d\n",a[0]);
return 0;
}