# Xorequ

### Output

2T行

i-1行表示第i个数据中问题一的解，

1

1

1

2

### HINT

x=1与x=2都是原方程的根，注意第一个问题的解

1<=N<=10^18

1<=T<=1000

# include<bits/stdc++.h>

using namespace std;
const int mod = 1e9 + 7;
struct lpl{
int n, m;
long long a[3][3];
}lin;
long long n;
long long f[66][2], pw[66];
int num[66];

lpl operator * (const lpl &A, const lpl &B)
{
lpl ret; ret.n = A.n; ret.m = B.m;
memset(ret.a, 0, sizeof(ret.a));
for(int i = 1; i <= ret.n; ++i)
for(int j = 1; j <= ret.m; ++j)
for(int k = 1; k <= A.m; ++k)
ret.a[i][j] = (ret.a[i][j] + A.a[i][k] * B.a[k][j] % mod) % mod;
return ret;
}

inline void prepare()
{
f[1][0] = 1; f[1][1] = 1; pw[0] = 1; pw[1] = 2;
for(int i = 2; i <= 63; ++i){
pw[i] = (pw[i - 1] << 1);
f[i][0] = f[i - 1][0] + f[i - 1][1];
f[i][1] = f[i - 1][0];
}
}

inline long long workk1(long long t)
{
long long ret = 0;
int len = 62;
while(pw[len] > t) len--;
for(int i = 1; i <= len + 1; ++i){
num[i] = (t & 1); t >>= 1;
}
num[len + 2] = 0;
for(int i = len + 1; i >= 1; --i){
if(num[i]){
ret += f[i][0];
if(num[i + 1]){
ret--; break;
}
}
}
return ret;
}

inline long long workk2(long long t)
{
lpl ret;
lin.a[1][1] = lin.a[1][2] = lin.a[2][1] = 1; lin.a[2][2] = 0; lin.n = lin.m = 2;
ret.a[1][1] = ret.a[2][2] = 1; ret.a[1][2] = ret.a[2][1] = 0; ret.n = ret.m = 2;
while(t){
if(t & 1)
ret = ret * lin;
t >>= 1; lin = lin * lin;
}
lpl ans; ans.n = 2; ans.m = 1; ans.a[1][1] = ans.a[2][1] = 1; ans.a[1][2] = ans.a[2][2] = 0;
ans = ret * ans;
return ans.a[1][1];
}

int main()
{
prepare();
int T; scanf("%d", &T);
while(T--){
scanf("%lld", &n);
printf("%lld\n%lld\n", workk1(n), workk2(n));
}
return 0;
}

posted @ 2018-06-06 18:23  沛霖  阅读(117)  评论(0编辑  收藏  举报