链接
题解
特征根法解除斐波那契额通项:
根据递推式
F
(
n
)
=
3
F
(
n
−
1
)
+
2
F
(
n
−
2
)
F(n)=3F(n-1)+2F(n-2)
F(n)=3F(n−1)+2F(n−2)
设
x
2
=
3
x
+
2
x^2 = 3x + 2
x2=3x+2
解得 x 1 = 3 − 17 2 , x 2 = 3 + 17 2 x_1=\frac{3-\sqrt {17} }{2},x_2=\frac{3+\sqrt {17} }{2} x1=23−17,x2=23+17
设 F ( n ) = c 1 x 1 n + c 2 x 2 n F(n) = c_1x_1^n + c_2x_2^n F(n)=c1x1n+c2x2n
将 F ( 0 ) = 0 , F ( 1 ) = 1 F(0)=0,F(1)=1 F(0)=0,F(1)=1带入,解得 c 1 = − 17 17 , c 2 = 17 17 c1=-\frac{\sqrt {17} }{17},c2=\frac{\sqrt {17} }{17} c1=−1717,c2=1717
所以 F ( n ) = − 17 17 ( 3 − 17 2 ) n + 17 17 ( 3 + 17 2 ) n F(n) = -\frac{\sqrt {17} }{17} (\frac{3-\sqrt {17} }{2})^n + \frac{\sqrt {17} }{17} (\frac{3+\sqrt {17} }{2})^n F(n)=−1717(23−17)n+1717(23+17)n
首先可以对 n n n欧拉降幂,然后用 b i g − s m a l l big-small big−small的方法预处理 x 1 , x 2 x_1,x_2 x1,x2的幂,每次就可以 O ( 1 ) O(1) O(1)回答了
代码
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 100010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define mod 998244353ll
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
ll c, f(1);
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
for(;isdigit(c);c=getchar())x=x*10+c-0x30;
return f*x;
}
ll fastpow(ll a, ll b, ll c)
{
ll t(a%c), ans(1ll);
for(;b;b>>=1,t=t*t%c)if(b&1)ans=ans*t%c;
return ans;
}
ll Q, N, r=473844410, a, b, big[2][maxn], small[2][maxn], _r=fastpow(r,mod-2,mod);
int main()
{
ll i, S=100000, lastans=0, ans=0;
a=(3-r+mod)*fastpow(2,mod-2,mod)%mod;
b=(3+r)*fastpow(2,mod-2,mod)%mod;
big[0][0]=big[1][0]=1;
small[0][0]=small[1][0]=1;
rep(i,S)
{
big[0][i]=fastpow(a,S*i,mod)%mod;
big[1][i]=fastpow(b,S*i,mod)%mod;
small[0][i]=small[0][i-1]*a%mod;
small[1][i]=small[1][i-1]*b%mod;
}
Q=read(), N=read();
while(Q--)
{
N ^= lastans*lastans;
ll n = N % (mod-1);
lastans = _r *( -big[0][n/S]*small[0][n%S]%mod + big[1][n/S]*small[1][n%S]%mod + mod ) %mod;
ans ^= lastans;
}
printf("%lld\n",ans);
return 0;
}