The Nth Item(线性方程O(1)求第n项)

original link - https://nanti.jisuanke.com/t/41355

题意:

F n = 3 F n − 1 + 2 F n − 2 , F 0 = 0 , F 1 = 1 F_n=3F_{n-1}+2F_{n-2},F_0=0,F_1=1 Fn=3Fn1+2Fn2,F0=0,F1=1的第 n n n % 998244353 \% 998244353 %998244353 n ∈ [ 1 , 1 e 18 ] n\in[1,1e18] n[1,1e18]

解析:

F n + 1 + − 3 + 17 2 F n = 3 + 17 2 ( F n + − 3 + 17 2 F n − 1 ) F_{n+1}+\dfrac{-3+\sqrt {17}}{2}F_{n}=\dfrac{3+\sqrt {17}}{2}(F_{n}+\dfrac{-3+\sqrt {17}}{2}F_{n-1}) Fn+1+23+17 Fn=23+17 (Fn+23+17 Fn1)

F n + 1 + − 3 − 17 2 F n = 3 − 17 2 ( F n + − 3 − 17 2 F n − 1 ) F_{n+1}+\dfrac{-3-\sqrt {17}}{2}F_{n}=\dfrac{3-\sqrt {17}}{2}(F_{n}+\dfrac{-3-\sqrt {17}}{2}F_{n-1}) Fn+1+2317 Fn=2317 (Fn+2317 Fn1)

∵ F 1 + − 3 + 17 2 F 0 = 1 \because F_1+\dfrac{-3+\sqrt {17}}{2}F_{0}=1 F1+23+17 F0=1

∴ F n + 1 + − 3 + 17 2 F n = ( 3 + 17 2 ) n , F n + 1 + − 3 − 17 2 F n = ( 3 − 17 2 ) n \therefore F_{n+1}+\dfrac{-3+\sqrt {17}}{2}F_{n}=(\dfrac{3+\sqrt {17}}{2})^n,F_{n+1}+\dfrac{-3-\sqrt {17}}{2}F_{n}=(\dfrac{3-\sqrt {17}}{2})^n Fn+1+23+17 Fn=(23+17 )n,Fn+1+2317 Fn=(2317 )n

∴ 17 F n = ( 3 + 17 2 ) n − ( 3 − 17 2 ) n \therefore \sqrt{17}F_n=(\dfrac{3+\sqrt {17}}{2})^n-(\dfrac{3-\sqrt {17}}{2})^n 17 Fn=(23+17 )n(2317 )n

怎么求 ( 3 + 17 2 ) n − ( 3 − 17 2 ) n (\dfrac{3+\sqrt {17}}{2})^n-(\dfrac{3-\sqrt {17}}{2})^n (23+17 )n(2317 )n呢?

首先 17 \sqrt{17} 17 用二次剩余展开为 524399943 524399943 524399943,前面那部分在模 998244353 998244353 998244353的循环节为 249561088 249561088 249561088,后面的为 29360128 29360128 29360128,那么就预处理下 x 100 k x^{100k} x100k,最后的 100 100 100内的也打一下。之后就可以 O ( 1 ) O(1) O(1)求了。

代码:

/*
 *  Author : Jk_Chen
 *    Date : 2019-09-08-14.12.16
 */
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define rep(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define per(i,a,b) for(int i=(int)(a);i>=(int)(b);i--)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pill pair<int, int>
#define fi first
#define se second
#define debug(x) cerr<<#x<<" = "<<x<<'\n';
const LL mod=998244353;
const int maxn=1e5+9;
LL rd(){ LL ans=0; char last=' ',ch=getchar();
    while(!(ch>='0' && ch<='9'))last=ch,ch=getchar();
    while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
    if(last=='-')ans=-ans; return ans;
}
/*_________________________________________________________head*/


LL Pow(LL a,LL b,LL mod){
    LL res=1;
    while(b>0){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
//524399943 473844410
LL sq17=524399943,inv2=Pow(2,mod-2,mod),inv_sq17=Pow(524399943,mod-2,mod);

LL P1[2495620],PP1[110];
LL P2[293611],PP2[110];

LL deal(LL n){
    if(n==0)return 0;
    if(n==1)return 1;
    LL n1=n%249561088;
    LL n2=n%29360128;
    LL m1=P1[n1/100]*PP1[n1%100]%mod;
    LL m2=P2[n2/100]*PP2[n2%100]%mod;
    return (m1+mod-m2)%mod*inv_sq17%mod;
}

int main(){
//    int ct=0;
//    LL now=1;
//    while(1){
//        ct++;
//        now=now*mul2%mod;
//        if(now==1)break;
//    }
//    printf("%d\n",ct);
    LL mul1=(3+sq17)*inv2%mod; // 249561088
    LL mul2=(mod+3-sq17)*inv2%mod; // 29360128
    PP1[0]=PP2[0]=1;
    rep(i,1,100)
        PP1[i]=PP1[i-1]*mul1%mod,
        PP2[i]=PP2[i-1]*mul2%mod;
    P1[0]=P2[0]=1;
    rep(i,1,2495610){
        P1[i]=P1[i-1]*PP1[100]%mod;
    }
    rep(i,1,293601){
        P2[i]=P2[i-1]*PP2[100]%mod;
    }

    LL q=rd(),n=rd();
    LL lastans=0;
    LL all=0;
    while(q--){
        n=(lastans*lastans)^n;
        LL ans=deal(n);
        lastans=ans;
        all^=ans;
    }
    printf("%lld\n",all);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值