<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;
}