D. Points and Powers of Two

https://codeforces.com/problemset/problem/988/D

题目描述

There are nn distinct points on a coordinate line, the coordinate of ii -th point equals to x_ixi​ . Choose a subset of the given set of points such that the distance between each pair of points in a subset is an integral power of two. It is necessary to consider each pair of points, not only adjacent. Note that any subset containing one element satisfies the condition above. Among all these subsets, choose a subset with maximum possible size.

In other words, you have to choose the maximum possible number of points x_{i_1}, x_{i_2}, \dots, x_{i_m}xi1​​,xi2​​,…,xim​​ such that for each pair x_{i_j}xij​​ , x_{i_k}xik​​ it is true that |x_{i_j} - x_{i_k}| = 2^d∣xij​​−xik​​∣=2d where dd is some non-negative integer number (not necessarily the same for each pair of points).

输入格式

The first line contains one integer nn ( 1 \le n \le 2 \cdot 10^51≤n≤2⋅105 ) — the number of points.

The second line contains nn pairwise distinct integers x_1, x_2, \dots, x_nx1​,x2​,…,xn​ ( -10^9 \le x_i \le 10^9−109≤xi​≤109 ) — the coordinates of points.

输出格式

In the first line print mm — the maximum possible number of points in a subset that satisfies the conditions described above.

In the second line print mm integers — the coordinates of points in the subset you have chosen.

If there are multiple answers, print any of them.

题意翻译

给你有n个数字的一个数列,问最多有多少个数字他们两两的差是2的幂次方数

输入输出样例

输入 #1复制

6
3 5 4 7 10 12

输出 #1复制

3
7 3 5

输入 #2复制

5
-1 2 5 8 11

输出 #2复制

1
8

说明/提示

In the first example the answer is [7, 3, 5][7,3,5] . Note, that |7-3|=4=2^2∣7−3∣=4=22 , |7-5|=2=2^1∣7−5∣=2=21 and |3-5|=2=2^1∣3−5∣=2=21 . You can't find a subset having more points satisfying the required property.


开始题目还读错了,以为要找一个序列中数字最大的.....

思路:满足条件的序列长度其实是<=3的。

证明:假设有长度为4的满足条件的序列,假设a<b<c<d。

令dist(a,b)=2^k,dist(b,c)=2^L.这两个满足条件则根据题意要有dist(a,c)=2^k+2^L==2^m,那么k就要等于L。

不然的话2^k+2^L==2^k*(1+2^|l-k|)不满足条件。

所以对于a,b,c满足这个条件,那么对于b,c,d也要满足这个条件,从而推出dist(a,b)=dist(b,c)=dist(c,d)=2^k。那么可得dis(a,d)=3*2^k。可见一定不满足条件。

发现了这个条件后直接枚举+二分就可以了。因为2^k在k属于0~30(>2e14)肯定能枚举完。

如果觉得手写二分出bug直接用STL的就好了。

再不想写可以直接放set里,在set里面判断有没有就行了(理论上set的查找是logn的)


最近碰到的大概三题和幂有关的题,幂的大小其实都是在一点小范围内的,是常数范围枚举的。

2^i+2^j==2^m的条件式i==j(推出这个式子就是解题关键)

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=2e5+1000;
typedef long long LL;
vector<LL>a;
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL n;cin>>n;
  for(LL i=0;i<n;i++){
  	LL x;cin>>x;
	a.push_back(x);//要用push 
  }
  sort(a.begin(),a.end());
  for(LL i=0;i<n;i++){
  	for(LL j=0;j<31;j++){
  		LL xl=a[i]-(1<<j);
		LL xr=a[i]+(1<<j);
		bool posl=binary_search(a.begin(),a.end(),xl);
		bool posr=binary_search(a.begin(),a.end(),xr);
		if(posl&&posr)
		{
			cout<<"3"<<endl;
			cout<<xl<<" "<<a[i]<<" "<<xr<<endl;
			return 0;	
		}		
	}
  }
  for(LL i=0;i<n;i++){
  	for(LL j=0;j<31;j++){
  	   LL xr=a[i]+(1<<j);
	   bool posl=binary_search(a.begin(),a.end(),xr);
	   if(posl)
	   {
	   		cout<<"2"<<endl;
			cout<<a[i]<<" "<<xr<<endl;
			return 0;	
	   }	 	
	}
  }
  cout<<"1"<<endl;
  cout<<a[0]<<endl;
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108364046