Solution - P5110 块速递推

主观难度:【3】

这啥?


我们需要求 \(a_n = (233a_{n-1}+666a_{n-2}) \bmod 10^9+7\)\(1 \le n < 2^{64}\)

无脑上矩阵快速幂能拿 \(6\) 分,由于数据范围不太可能使用矩阵光速幂。

然后 Hootime 就去看了第一篇题解。

我们设 \(a_{n+2}+pa_{n+1} = q(a_{n+1} + pa_n)\)

简单移项可得 \(a_{n+2} = (q-p)a_{n+1}+pqa_n\),得到 \( \begin{cases} q - p = 233 \\ pq = 666 \end{cases} \),整理得 \(p^2 + 233p - 666 = 0\)。运用初二学的数学可得 \(p = \frac{-233 \pm \sqrt {56953}}{2}\),于是 \(q = \frac{233 \pm \sqrt {56953}}{2}\)

我们设 \(b_n = (a_{n+1}+ba_n)\),发现 \(b_n = qb_{n-1}\)。又有 \(b_0 = 1\),于是发现 \(b_n\) 是等比数列。

发现当 \(p\)\(\frac{-233 + \sqrt {56953}}{2}\) 时有 \(a_{n+1}-\frac{-233 + {56953}}{2}a_{n} = b_n = (\frac{233 + \sqrt {56953}}{2})^n\),当 \(p\)\(\frac{-233 - \sqrt {56953}}{2}\) 时有 \(a_{n+1}-\frac{-233 - {56953}}{2}a_{n} = b_n = (\frac{233 - \sqrt {56953}}{2})^n\)

上两式相减得 \(\sqrt{56953}a_n = (\frac{233 + \sqrt {56953}}{2})^n - (\frac{233 - \sqrt {56953}}{2})^n\),即 \(a_n = \frac{(\frac{233 + \sqrt {56953}}{2})^n - (\frac{233 - \sqrt {56953}}{2})^n}{\sqrt{56953}}\)

打表得 \(\sqrt{56953}\) 在模 \(10^9+7\) 意义下可以表示为 \(188305837\)。由于 \(n\) 在子树上,由费马小定理可得 \(a\) 的循环节是 \(10^9+6\),使用光速幂即可。

#include <bits/stdc++.h>
#define llong long long
#define ullong unsigned long long
using namespace std;

namespace Mker
{
	unsigned long long SA,SB,SC;
	void init(){scanf("%llu%llu%llu",&SA,&SB,&SC);}
	unsigned long long rand()
	{
	    SA^=SA<<32,SA^=SA>>13,SA^=SA<<1;
	    unsigned long long t=SA;
		SA=SB,SB=SC,SC^=t^SA;return SC;
	}
}

constexpr llong p        = 1000000007;
constexpr llong sq56953  = 188305837;
constexpr llong inv2     = 500000004;
constexpr llong inv56953 = 233230706;

llong Powa1[1<<15], Powa2[1<<15];
llong Powb1[1<<15], Powb2[1<<15];

void _prework(){
    llong a = (233+sq56953  )*inv2%p;
    llong b = (233-sq56953+p)*inv2%p;
    Powa1[0] = Powb1[0] = Powa2[0] = Powb2[0] = 1;
    for(int i = 1; i < (1<<15); ++i)
        Powa1[i] = (Powa1[i-1]*a)%p, Powb1[i] = (Powb1[i-1]*b)%p;
    llong a15 = Powa1[(1<<15)-1]*a%p;
    llong b15 = Powb1[(1<<15)-1]*b%p;
    for(int i = 1; i < (1<<15); ++i)
        Powa2[i] = Powa2[i-1]*a15%p, Powb2[i] = Powb2[i-1]*b15%p;
    return;
}
#define Powa(x) (Powa1[x&((1<<15)-1)]*Powa2[x>>15]%p)
#define Powb(x) (Powb1[x&((1<<15)-1)]*Powb2[x>>15]%p)

int T;
ullong ans;
int main(){
    scanf("%d", &T);
    Mker::init();
    _prework();
    while(T--){
        llong n = Mker::rand()%(p-1);
        ans ^= (Powa(n)-Powb(n)+p)%p*inv56953%p;
    }
    cout << ans;
    return 0;
}

posted @ 2026-03-18 20:51  Hootime  阅读(1)  评论(0)    收藏  举报