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

浙公网安备 33010602011771号