常系数齐次线性递推
给定 n,k,f1∼fk,a0∼ak−1,若:
ai=j=1∑kfjai−j
求 anmod998244353 的值,其中 n=109,k=32000。
题目链接:P4723。
考虑一个朴素的斐波那契数列的展开过程:
a5=a4+a3=2a3+a2=3a2+2a1=5a1+3a0
如果从一个多项式的角度来看:
0x0+0x1+0x2+0x3+0x4+1x50x0+0x1+0x2+1x3+1x4+0x50x0+0x1+1x2+2x3+0x4+0x50x0+2x1+3x2+0x3+0x4+0x53x0+5x1+0x2+0x3+0x4+0x5
做的事情就是不断地减去 λxμ(x2−x−1),这就是一个取模的过程。因此 an 的取值就 xnmodF(x) 有关,其中 F(x) 是数列的特征多项式。具体地:
F(x)=xk+j=1∑k−fjxk−j
则 an 满足的式子是:
an=i=0∑k−1[xi](xnmodF(x))ai
当然,需要 a0∼ak−1 已知,否则也推不出来定值。多项式的题目最经典的错误是没有清空数组,只能说多注意一下吧,这种错误很难调。这样快速幂加上取模的复杂度是 O(klogklogn),如果是矩阵乘法需要 O(k3logn),还是有显著的优化的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <bits/stdc++.h> using namespace std;
int n, k, res, a[N]; Poly A, B;
signed main() { ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); cin >> n >> k; B.resize(k); for (int i = 0; i < k; i++) cin >> B[k-i-1], B[k-i-1] = ((-B[k-i-1]) % P + P) % P; B[k] = 1; for (int i = 0; i < k; i++) cin >> a[i], a[i] = (a[i] % P + P) % P; A.resize(1); A[1] = 1; A = A.fqmi(n, B); for (int i = 0; i < k; i++) res = (res + A[i] * a[i]) % P; cout << res << endl; return 0; }
|