2019-南昌网络赛 The Nth Item(矩阵快速幂+记忆化||找规律)
For a series FF:
\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 NN, the answer AA is the value F(N)F(N) modulo 998244353998244353.
Moreover, the input data is given in the form of encryption, only the number of queries QQ and the first query N_1N1 are given. For the others, the query N_i(2\leq i\leq Q)Ni(2≤i≤Q) is defined as the xor of the previous N_{i-1}Ni−1 and the square of the previous answer A_{i-1}Ai−1. For example, if the first query N_1N1 is 22, the answer A_1A1 is 33, then the second query N_2N2 is 2 \ xor \ ( 3*3)=112 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\ xor\ A_2 ... xor\ A_QA1 xor A2...xor AQ.
Input
The input contains two integers, Q, NQ,N, 1\ \leq \ Q \leq 10^7,0\ \leq\ N \leq 10^{18}1 ≤ Q≤107,0 ≤ N≤1018. QQ representing the number of queries and NN representing the first query.
Output:
An integer representing the final answer.
样例输入复制
17 473844410
样例输出复制
903193081
时限1s,虽然普通矩阵快速幂肯定过不了,但是还是交了一发试了一下
后来也想到用记忆化优化,不过忽视了取模的过程中n并不是越来越大的,,并且时间也不够了,于是这个题就凉了
据说正解是找规律,先挖个坑。
下面是加入map记忆化的676ms AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2;
const ll mod=998244353;
inline ll read()///没错 快读是偷来的
{
ll x=0;
char c=0;
c=getchar();
while(isdigit(c))
{
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x;
}
struct mat
{
ll a[N][N];
};
//ll qmul(ll a,ll b)///哦对 还有这个问题 我也不知道为什么加上快速积就会超时 难道是因为数据本来没有很大 多此一举???? 请教路过的大佬 orz
//{
// ll ans=0,res=a;
// while(b)
// {
// if(b&1)
// ans=(ans+res);
// res=(res+res);
// b>>=1;
// }
// return ans;
//}
mat mat_mul(mat x,mat y)
{
mat res;
memset(res.a,0,sizeof(res.a));
for(int i=0; i<2; i++)
{
for(int j=0; j<2; j++)
{
for(int k=0; k<2; k++)
res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
}
}
return res;
}
ll mat_pow(ll n)
{
if(n<0)
{
return 0;
}
mat c,res;
c.a[0][0]=3;
c.a[0][1]=2;
c.a[1][0]=1;
c.a[1][1]=0;
memset(res.a,0,sizeof(res.a));
for(int i=0; i<2; i++)
res.a[i][i]=1;
while(n)
{
if(n&1)
res=mat_mul(res,c);
c=mat_mul(c,c);
n=n>>1;
}
return res.a[0][0];
}
int main()
{
int q;
ll n;
q=read();
n=read();
map<ll,ll>mp;
mp.clear();
ll ans=0;
ll cnt=n;
mp[0]=0;
mp[1]=1;
for(int i=1; i<=q; i++)
{
if(mp.count(cnt)!=0)
{
ans^=mp[cnt];
cnt^=(mp[cnt]*mp[cnt]);
}
else
{
ll tmp=mat_pow(cnt-1);
mp[cnt]=tmp;
ans^=tmp;
cnt^=(tmp*tmp);
}
}
printf("%lld\n",ans);
return 0;
}