【CodeForces】【数学】988D Points and Powers of Two

CodeForces 988D Points and Powers of Two

题目

◇题目传送门◆

题目大意

有一个 N(1N2×105) N ( 1 ≤ N ≤ 2 × 10 5 ) 个点的点集,我们要在这个点集中选出尽可能多的点,使任意两点间距离的绝对值是 2 2 的整数次幂。

思路

我们到底最多可以选多少个点呢?我们来推导一下:

1.只有一个点时:点集中没有可以和它作差的点,故此情况成立。

2.有两个点时:只要两点间距离为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
图1
可得: 2k1+2k2=2d 2 k 1 + 2 k 2 = 2 d
不妨设 k1k2 k 1 ≤ k 2
则: 1+2k2k1=2dk1 1 + 2 k 2 − k 1 = 2 d − k 1
整理可得: 2k2k1×(2dk21)=1 2 k 2 − k 1 × ( 2 d − k 2 − 1 ) = 1
由题意可知: k10,k20,d0 k 1 ≥ 0 , k 2 ≥ 0 , d ≥ 0
所以: 2k2k1>0 2 k 2 − k 1 > 0 2dk2>0 2 d − k 2 > 0
所以: k2k1=0,dk2=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标记位于位置i的点是否存在于点集中。

正解代码

#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;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值