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
#include
#include
#include
#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<
cin>>q>>n;
ll last=n;
ll ans=0;
while(q--)
{
ll now=f(last%per);
ans^=now;
//cout<
last=last^(now*now);
}
cout<<ans<<endl;
return 0;
}