codeforces 988D

这题的关键就是推出有且仅有 1个、2个、3个三种情况。然后枚举+二分即可。话说通过这题竟然意外弥补了自己二分上的一个小缺陷~(ps:果然,应该再睡一会再来补题的,凌晨打完现在补题,我都不知道我敲得是什么鬼)


证明:不妨先对序列排个序,那么对于数x,它的下一个数一定是x+2^d,在第一个数是x,第二个数是x+2^d的情况下,第三个数只能是x+2*2^d,因为首先第三个数要比第一个数大2的幂次倍,所以它等于 x + 2^k,又因为还要和第二个数满足条件,所以他们的差必须是2的幂次,做减法:(2^y - 1) * 2^d,其中y+d = k,而可以使(2^y - 1) 为2的幂次的取值有且仅有1,即 其取值为 x + 2 * 2 ^ d,命题得证。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
ll a[200200];

ll f(ll d){
	ll ans = 1;
	for(ll i = 0; i < d; i ++)
		ans *= 2;
	return ans;
}
int main(){
	ll n;
	cin >> n;
	for(ll i = 0; i < n; i ++)
		cin >> a[i];
	sort(a, a + n);
	
	ll d;
	vector <ll> ans;
	for(ll i = 0; i < n; i ++){
		for(ll j = 0; a[i] + f(j) <= a[n - 1]; j ++){ //又写出一个bug 
			vector <ll> temp;
			ll t1 = a[i] + f(j);
			ll t2 = a[i] + 2 * f(j);
			ll ul = i, ur = n - 1;    //注意二分的边界,左开右闭,妙处无限 
			while(ur - ul > 1){
				ll mid = (ul + ur) / 2;
				if(a[mid] >= t1)
					ur = mid;
				else
					ul = mid;
			}
			if(a[ur] == t1){
				temp. push_back(a[i]);
				temp. push_back(t1);
				ul = ur, ur = n - 1;
				while(ur - ul > 1){
					ll mid = (ul + ur) / 2;
					if(a[mid] >= t2)
						ur = mid;
					else
						ul = mid;
				}
				if(a[ur] == t2){
					temp. push_back(t2);
				}
			}
			if(temp. size() > ans. size()){
				ans. clear();
				for(int i = 0; i < temp. size(); i ++)
					ans. push_back(temp[i]);
			}
		}
	}
	if(ans. size() == 0)   //没仔细读题搞出来的bug 
		ans. push_back(a[0]);
	cout << ans. size() << endl;
	for(int i = 0; i < ans. size() - 1; i ++)
		cout << ans[i] << ' ';
	cout << ans[ans. size() - 1] << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/80546578