For a series F:
F
(
0
)
=
0
,
F
(
1
)
=
1
F
(
n
)
=
3
∗
F
(
n
−
1
)
+
2
∗
F
(
n
−
2
)
,
(
n
≥
2
)
\displaystyle \begin{gathered} F(0) = 0,F(1) = 1\\ F(n) = 3*F(n-1)+2*F(n-2),(n \geq 2) \end{gathered}
F(0)=0,F(1)=1F(n)=3∗F(n−1)+2∗F(n−2),(n≥2)
We have some queries. For each query N, the answer A is the value F(N) modulo 998244353.
Moreover, the input data is given in the form of encryption, only the number of queries Q and the first query N 1 N_1 N1are given. For the others, the query N i ( 2 ≤ i ≤ Q ) N_i(2\leq i\leq Q) Ni(2≤i≤Q)is defined as the xor of the previous N i − 1 N_{i-1} Ni−1and the square of the previous answer A i − 1 A_{i-1} Ai−1 For example, if the first query N 1 N_1 N1is 2, the answer A 1 A_1 A1 is 3, then the second query $N_2 $is 2 x o r ( 3 ∗ 3 ) = 11 2 \ xor \ ( 3*3)=11 2 xor (3∗3)=11.
Finally, you don’t need to output all the answers for every query, you just need to output the xor of each query’s answer
A
1
x
o
r
A
2
.
.
.
x
o
r
A
Q
A_1\ xor\ A_2 ... xor\ A_Q
A1 xor A2...xor AQ
.
Input
The input contains two integers, Q,N,
1
≤
Q
≤
1
0
7
,
0
≤
N
≤
1
0
18
1\ \leq \ Q \leq 10^7,0\ \leq\ N \leq 10^{18}
1 ≤ Q≤107,0 ≤ N≤1018
Q representing the number of queries and N representing the first query.
Output:
An integer representing the final answer.
样例输入
17 473844410
样例输出
903193081
我连二次剩余直接用板子都敲出来了,以为可以优化矩阵的常数,没想过用分块,还是分块大法好
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
#define ll long long
#define mod 998244353
using namespace std;
const int maxx = 200005;
struct M
{
ll m[2][2];
friend M operator *(M x1,M x2)
{
M tmp;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
{
tmp.m[i][j]=x1.m[i][0]*x2.m[0][j]%mod+x1.m[i][1]*x2.m[1][j]%mod;
if(tmp.m[i][j]>=mod)tmp.m[i][j]-=mod;
}
return tmp;
}
};
M P(M a,ll b)
{
M ans={1,0,0,1};
while(b)
{
if(b&1)ans=ans*a;
a=a*a;
b>>=1;
}
return ans;
}
int per=499122176;
M block[5000005];
M res[1005];
ll f(int x)
{
M ans=block[x/100]*res[x%100];
return ans.m[1][0];
}
ll n,q;
int main()
{
res[0]={1,0,0,1};
res[1]={3,2,1,0};
for(int i=2;i<=100;i++)res[i]=res[i-1]*res[1];
block[0]=res[0];
for(int i=1;i<=5e6;i++)block[i]=block[i-1]*res[100];
//for(int i=1;i<100;i++)cout<<i<<" "<<f(i)<<endl;
cin>>q>>n;
ll last=n;
ll ans=0;
while(q--)
{
ll now=f(last%per);
ans^=now;
//cout<<now<<endl;
last=last^(now*now);
}
cout<<ans<<endl;
return 0;
}