【题意】
【分析】
按位异或有一个性质:若
a
⨁
b
=
c
a \bigoplus b=c
a⨁b=c, 则
a
⨁
c
=
b
a \bigoplus c = b
a⨁c=b。
所以说:
x
⨁
3
x
=
2
x
⟺
x
⨁
2
x
=
3
x
⟺
x
⨁
2
x
=
x
+
2
x
x\bigoplus 3x=2x \Longleftrightarrow x \bigoplus 2x =3x \Longleftrightarrow x \bigoplus 2x=x+2x
x⨁3x=2x⟺x⨁2x=3x⟺x⨁2x=x+2x
又有:
2
x
⟺
x
<
<
1
2x \Longleftrightarrow x<<1
2x⟺x<<1
所以
x
⨁
2
x
=
x
+
2
x
⟺
x
&
(
x
<
<
1
)
=
0
x \bigoplus 2x=x+2x \Longleftrightarrow x \& (x<<1)=0
x⨁2x=x+2x⟺x&(x<<1)=0
即x的二进制不存在相邻的1。
于是,对于第一问,设
f
(
i
,
0
/
1
)
f(i,0/1)
f(i,0/1)为当前做到第
i
i
i位,前一位为0/1,然后按照题意转移即可。
然而,对于第二问,由于位数太长,所以不能用上面那个方法。
我们设
g
(
i
)
=
f
(
i
,
0
)
+
f
(
i
,
1
)
g(i)=f(i,0)+f(i,1)
g(i)=f(i,0)+f(i,1),然后对
g
(
i
)
g(i)
g(i)变形:
g
(
i
)
=
f
(
i
,
0
)
+
f
(
i
,
1
)
=
f
(
i
−
1
,
0
)
+
f
(
i
−
1
,
1
)
+
f
(
i
−
1
,
0
)
=
g
(
i
−
1
)
+
f
(
i
−
2
,
0
)
+
f
(
i
−
2
,
1
)
=
g
(
i
−
1
)
+
g
(
i
−
2
)
\begin{aligned} g(i)&=f(i,0)+f(i,1)\\&=f(i-1,0)+f(i-1,1)+f(i-1,0)\\&=g(i-1)+f(i-2,0)+f(i-2,1)\\&=g(i-1)+g(i-2) \end{aligned}
g(i)=f(i,0)+f(i,1)=f(i−1,0)+f(i−1,1)+f(i−1,0)=g(i−1)+f(i−2,0)+f(i−2,1)=g(i−1)+g(i−2)
其中:
g
(
1
)
=
2
,
g
(
2
)
=
3
g(1)=2,g(2)=3
g(1)=2,g(2)=3
发现这是一个斐波那契数列,
g
(
i
)
g(i)
g(i)为其
i
+
2
i+2
i+2项,直接矩阵加速即可。
【代码】
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
const int mn = 100, mod = 1e9 + 7;
struct matrix{
ll a[3][3];
matrix operator *(const matrix b) const
{
matrix c;
memset(c.a, 0, sizeof c.a);
for(int i = 1; i <= 2; i++)
for(int j = 1; j <= 2; j++)
for(int k = 1; k <= 2; k++)
c.a[i][j] += (a[i][k] * b.a[k][j]) % mod, c.a[i][j] %= mod;
return c;
}
}ret, h;
int d[mn];
ll f[mn][2];
ll dp(int pos, int las, bool lim)
{
if(!pos)
return 1;
if(!lim && ~f[pos][las])
return f[pos][las];
int m = lim ? d[pos] : 1;
ll ans = 0;
for(int i = 0; i <= m; i++)
if(las == 1 && i == 1)
continue;
else
ans += dp(pos - 1, i, lim && i == m);
if(!lim)
f[pos][las] = ans;
return ans;
}
inline ll calc(ll n)
{
int cnt = 0;
while(n)
d[++cnt] = n & 1, n >>= 1;
return dp(cnt, -1, 1);
}
inline ll ksm(ll b)
{
while(b)
{
if(b & 1)
ret = ret * h;
h = h * h, b >>= 1;
}
memset(h.a, 0, sizeof h.a);
h.a[1][1] = 1, h = h * ret;
return h.a[1][1];
}
inline void init()
{
memset(ret.a, 0, sizeof ret.a), memset(h.a, 0, sizeof h.a);
ret.a[1][1] = ret.a[2][2] = 1, h.a[1][1] = h.a[2][1] = h.a[1][2] = 1;
}
int main()
{
int t;
ll n;
scanf("%d", &t), memset(f, -1, sizeof f);
while(t--)
{
scanf("%lld", &n), init();
printf("%lld\n%lld\n", calc(n) - 1, ksm(n + 1));
}
}