小Y在研究数字的时候,发现了一个神奇的等式方程,他屈指算了一下有很多正整数x满足这个等式,比如1和2,现在问题来了,他想知道从小到大第N个满足这个等式的正整数,请你用程序帮他计算一下。
(表示按位异或运算)
输入描述:
第一行是一个正整数,表示查询次数。
接着有T行,每行有一个正整数,表示小Y的查询。
输出描述:
对于每一个查询N,输出第N个满足题中等式的正整数,并换行。
思路:一看即为规律题目,由于涉及异或,所以可以打表查看每个数的二进制,发现
1
10
100
101
1000
1001
1010
让相同位数的数为一组,可以发现符合斐波拉底数列的基本要求,所以我们可以利用斐波拉底先去寻找它所在的组数,而每个组的第一个数(标志数)均为2的n次方,然后确定它所在的组数t,减去组数b[t-1],来确定其他位的情况,判断其他位在其他的标志数所对应二进制的数字上是否有1
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+50;
ll a[maxn];
ll b[maxn];
ll bit[maxn];
int main()
{
int t;
cin>>t;
a[1]=1;
a[2]=1;
a[3]=1;
bit[1]=1;
b[0]=0;
//初始化
for(int i=2; i<=63; i++) //确定标志数
bit[i]=bit[i-1]*2;
for(int i=4; i<=64; i++)
a[i]=a[i-1]+a[i-2];
for(int i=1; i<=64; i++) //斐波拉底求和
b[i]=b[i-1]+a[i];
while(t--)
{
ll n,ans=0,index;
cin>>n;
ll index=n;
while(index)
{
int t=upper_bound(b+1,b+64,index)-b; //寻找最后一个大于等于t的组数
index=index-b[t-1]; //减去当前的长度
ans+=bit[t-1]; //进行进位处理
}
cout<<ans<<endl;
}
return 0;
}