CodeForces

原文地址:https://blog.csdn.net/weixin_39453270/article/details/80548442

博主已经讲的很好了

题意:

  从一个序列中,选出一个集合,使得集合里的数两两差得绝对值为2得幂次

解析:

 对于这个题目,我们需要发现这么一个结论,答案中形成的集合的大小最大只能达到3。

    下面对这个命题进行简单的证明:

    我们设当集合大小=3,三个数从小到大分别为a,b,c,即要符合条件,则需要满足:

    b-a=k1 (1)

    c-b=k2 (2)

    c-a=k3 (3)

    将(2)+(1)可得 c-a=k1+k2,再根据(3)可得

    k3=k1+k2。

    因为我们知道,要满足题意,k1,k2,k3都必须为2的幂。而要使得2^a1+2^b1==2^c1成立,则不难得出,当且仅当a1==b1时成立,即k1==k2时成立,此时,不难发现,a,b,c三个数是形成一个以2得幂次为公差的等差数列。

    而当集合的大小>=4时,设大小为4,四个数由大到小分别为a,b,c,d。则根据上面的证明,则我们要满足答案,则需要abc、abd、acd、bcd......所有的三元组都需要满足上述式子。显然这是不成立的,因此,大小大于3的答案是不合理的。

    因此,我们只需要考虑三个以内的答案即可。首先我们需要开一个set记录数列中的数。而因为存在的几个数是需要满足等差数列的,因此,我们可以枚举1到1e9中2的幂次j,判断a+j和a+j+j是否在set内即可。倘若都不在set内,则随便输出一个数即可。

#include <bits/stdc++.h>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 1e6+5, INF = 0x7fffffff;
typedef long long LL;
LL a[maxn];
set<LL> s;

int main()
{
    int n;
    cin>> n;
    for(int i=0; i<n; i++)
    {
        cin>> 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] + j*2))
            {
                cout<< "3" <<endl;
                cout<< a[i] << " " << a[i] + j << " " << a[i] + j*2 <<endl;
                return 0;
            }
    }
    for(int i=0; i<n; i++)
    {
        for(LL j=1; j<=2e9; j<<=1)
            if(s.count(a[i]+j))
            {
                cout<< "2" <<endl;
                cout<< a[i] << " " << a[i] + j <<endl;
                return 0;
            }
    }
    cout<< 1 <<endl;
    cout<< a[0] <<endl;



    return 0;
}
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
原文地址:https://www.cnblogs.com/WTSRUVF/p/9531118.html