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;
}

 

全部评论

相关推荐

ArisRobert:统一解释一下,第4点的意思是,公司按需通知员工,没被通知到的员工是没法去上班的,所以只要没被通知到,就自动离职。就是一种比较抽象的裁员。
点赞 评论 收藏
分享
昨天 11:21
门头沟学院 Java
总包48.5w,意想不到的价格
无情咸鱼王的秋招日记之薛定谔的Offer:R
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务