Codeforces Round #486 (Div. 3) D. Points and Powers of Two

本文解析了CodeForces上的一道难题,通过数学证明得出最优解不超过3个数,并提供了一种有效的算法实现,利用等差数列的特性解决两两数之间的差值为2的幂的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接http://codeforces.com/contest/988/problem/D

题目分析 : 给你一个大小为n的数列,问你最多能够在这个这n个数中选取多少个,使得由他们组成的集合中,两两之间的差的绝对值为2的幂。

题目建模

这个题最大的难点,在于分析出:这个n<=3;简单证明一下

当n==1||n==2,结论肯定成立

当n==3时

三个数从小到大分别为a,b,c,即要符合条件,则需要满足:

    b-a=x; c-b=y; c-a=z;    (1)

    c-b=y     (2)

    c-a=z     (3)

    将(2)+(1)可得 ,再根据(3)可得

      x+y=z

    因为我们知道,要满足题意,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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值