Codeforces 988D 题解

<988D>

题意:

给定若干个数,问在其中挑选几个数组成一个集合,使得集合中任意以两个数a, b(a > b)的差值均为2^n。

思路:

这题要先找规律,这个规律就是,集合中的元素最多有3个,证明如下:

假设集合内目前只有三个元素:x,y,z 且 x < y < z

则根据题意,有如下关系:

z - y = 2^a (1)

y - x = 2^b (2)

z - x = 2^c (3)

所以由 (1)式 + (2)式,再与 (3)式联立,得 z - x = 2^a + 2^b = 2^c,由此可得,当且仅当

2^c = 2 * 2^b = 2 * 2^a 时上述等式成立,即 a = b = c - 1;

所以由 a = b, 得 2^a = 2^b,即 z - y = y - x,所以 x,y,z构成等差数列,

由上可知,当集合中有四个元素的时候,x < y < z < k 时,显然就不成立了,因为你要满足从中挑出的任意三个元素满足等差数列,比如 <x, y, k> 或 <x, z, k>时就不成立了,因为x, y, z, k满足等差数列,且公差不能为0,所以它的三元组子集就未必满足构成等差这个条件了。

找到这个规律以后就好办了,存进集合set中,然后在1~2e9中枚举2^n,再加到集合元素a[i]上,看有几个在集合中即可,如果够不成等差数列,即只有一个元素的时候,那就输出a[1]就好了。

本人AC代码:

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 7;
map <int, int> mp;
vector <int> vec;
queue <int> qua;
set <ll> sst;
int n;
ll a[maxn];

int main() {
	cin >> n;
	for(int i = 1; i <= n; i++) {
		cin >> a[i];
		sst.insert(a[i]);
	}
	for(int i = 1; i <= n; i++) {
		for(ll j = 1; j <= 2e9; j *= 2) {
			if(sst.count(a[i] + j) && sst.count(a[i] + 2 * j)) {
				puts("3");
				printf("%I64d %I64d %I64d\n", a[i], a[i] + j, a[i] + 2 * j);
				return 0;
			}
		}
	}
	for(int i = 1; i <= n; i++) {
		for(ll j = 1; j <= 2e9; j *= 2) {
			if(sst.count(a[i] + j)) {
				puts("2");
				printf("%I64d %I64d\n", a[i], a[i] + j);
				return 0;
			}
		}
	}
	puts("1");
	cout << a[1] << endl;
}

猜你喜欢

转载自blog.csdn.net/ericgipsy/article/details/80717377