CF988 D. Points and Powers of Two

题目链接:http://codeforces.com/contest/988/problem/D
题意:给n个互不相同的数,在里面选取一些数组成集合,满足集合内的数任意两两绝对值之差是2的幂,求这个集合能构成的最多元素个数并分别输出。
题解:可以证明这个集合最大是3。假设三个数a,b,c能构成这个集合(a < b < c),则有b - a = 2 ^ x,c - b = 2 ^ y,c - a = 2 ^ z,则2 ^ x + 2 ^ y = 2 ^ z
显然z > x并且z > y,不妨设x < y,两边同时除以2 ^ x,则 1 + 2^(y - x) = 2^(z - x),要使该等式成立,则y - x = 0,z - x = 1
即 x = y = z - 1,进一步的,a + c = 2 * b
假设存在4个数a,b,c,d(a < b < c < d)能构成该集合,依据上面的结论有 a + c = 2 * b,a + d = 2 * b,推出 c = d,矛盾,则结论成立。
知道了最多有三个,则可以枚举出现的集合大小。

#include<map>
#include<iostream>
using namespace std;
typedef long long ll;
map<ll,ll>arr;
const int maxn = 2e5 +5;
ll a[maxn];
ll s[34];
int main()
{
    s[0] = 1;
    for(int i = 0; i <= 30; i ++){
        s[i + 1] = s[i] * 2;
    }
   int n;
   cin>>n;
    for(int i = 0; i < n; i ++){
        cin>>a[i];
        arr[a[i]] = 1;
    }
    int cnt = 0;
    ll p1 = 0,p2 = 0, p3 = 0;
    for(int i = 0; i < n; i ++){
        for(int j = 0; j <= 31; j ++){
            if(arr.find(a[i] + s[j])!= arr.end()){
               if(((2 * a[i] + s[j])%2==0)&&arr.find((2 * a[i] + s[j])/2)!=arr.end()){
                    cout<<3<<endl;
                    cout<<a[i]<<" "<<a[i] + s[j]<<" "<<(2 * a[i]+s[j]) /2<<endl;
                    return 0;
               }
               else {
                cnt = 2;
                p1 = a[i];
                p2 = a[i] + s[j];
               }
            }
        }
    }
    if(cnt == 2){
        cout<<2<<endl;
        cout<<p1<<" "<<p2<<endl;
    }
    else{
        cout<<1<<endl;
        cout<<a[0]<<endl;
    }
    return 0;

}

猜你喜欢

转载自www.cnblogs.com/goxy/p/9154541.html