给定一个数列a:
当n<=2时,a[n]=n
当n>2,且n是奇数时,a[n]=2a[n-1]
当n>2,且n是偶数时,a[n]=a[n-1]+r[n-1]
其中r[n-1]=mex(|a[i]-a[j]|)(1<=i<=j<=n-1),mex{S}表示最小的不在S集合里面的非负整数。
数列a的前若干项依次为:1,2,4,8,16,21,42,51,102,112,224,235,470,486,972,990,1980。
可以证明,对于任意正整数x,只存在唯一一对整数(p,q)满足x=a[p]-a[q],定义为repr(x)。
比如repr(17)=(6,3),repr(18)=(16,15)。
现有n个询问,每次给定一个正整数x,请求出repr(x)。
第一行包含一个正整数n(1<=n<=10^5)。
接下来n行,每行一个正整数x(1<=x<=10^9),表示一个询问。
输出n行,每行两个正整数p,q,依次回答每个询问。
#pragma GCC optimize("O2")
#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
char buf[10000000], *ptr = buf - 1;
inline int readint(){
int n = 0;
while(*++ptr < ‘0‘ || *ptr > ‘9‘);
while(*ptr <= ‘9‘ && *ptr >= ‘0‘) n = (n << 1) + (n << 3) + (*ptr++ & 15);
return n;
}
int a[100], b[1000000], cnt = 0;
map<int, pair<int, int> > mp;
int main(){
fread(buf, sizeof(char), sizeof(buf), stdin);
mp.clear();
a[1] = 1;
a[2] = 2;
mp[1] = make_pair(2, 1);
int last, tot;
for(last = 1, tot = 3; ; tot++){
if(tot & 1) a[tot] = a[tot - 1] + a[tot - 1];
else{
while(mp.count(last)) last++;
a[tot] = a[tot - 1] + last;
}
for(int j = 1; j < tot; j++)
if(!mp.count(a[tot] - a[j]))
mp[a[tot] - a[j]] = make_pair(tot, j);
if(!(tot & 1) && a[tot] > 1000000000) break;
}
map<int, pair<int, int> >::iterator it;
for(it = mp.begin(); it != mp.end(); ++it)
b[++cnt] = it -> first;
int n = readint(), x, y;
while(n--){
x = readint();
if(mp.count(x)) printf("%d %d\n", mp[x].first, mp[x].second);
else{
y = lower_bound(b + 1, b + cnt + 1, x) - (b + 1);
printf("%d %d\n", tot + (x - y) * 2, tot + (x - y) * 2 - 1);
}
}
return 0;
}