递推
ssl 1532
题目大意
给出数列a0,a1…ana_0,a_1…a_na0,a1…an和fff的前n−1n-1n−1项f0,f1…fn−1f_0,f_1…f_{n-1}f0,f1…fn−1
fi=a0∗fi−n+a1∗fi−(n−1)+...+an−1∗fi−1+anf_i=a_0*f_{i-n}+a_1*f_{i-(n-1)}+...+a_{n-1}*f_{i-1}+a_nfi=a0∗fi−n+a1∗fi−(n−1)+...+an−1∗fi−1+an
现在让你求fkf_kfk(结果对9973取模)
输入样例
2 10
1 1 0
0 1
输出样例
55
数据范围
1⩽n⩽k⩽10181⩽ai,fi⩽1041\leqslant n\leqslant k\leqslant10^{18}\\1\leqslant a_i,fi\leqslant10^41⩽n⩽k⩽10181⩽ai,fi⩽104
解题思路
k较大,无法直接递推,我们考虑矩阵乘法
设矩阵
[fi−nfi−(n−1)…fi−11]\begin{bmatrix} f_{i-n} &f_{i-(n-1)} & … & f_{i-1} & 1 \end{bmatrix}[fi−nfi−(n−1)…fi−11]
fi−n−fi−2f_{i-n}-f_{i-2}fi−n−fi−2直接等于下一位
fi−1f_{i-1}fi−1就是前面n项乘对应的a,然后加上最后一个1乘ana_nan
1不变
得出需要乘的矩阵后快速幂即可
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define wyc 9973
ll n, k;
struct matrix
{ll n, m, a[100][100];matrix operator *(matrix const &b)const{matrix c;c.n = n;c.m = b.m;for (int i = 1; i <= c.n; ++i)for (int j = 1; j <= c.m; ++j)c.a[i][j] = 0;for (int i = 1; i <= c.n; ++i)for (int k = 1; k <= m; ++k)for (int j = 1; j <= c.m; ++j)c.a[i][j] = (c.a[i][j] + a[i][k] * b.a[k][j] % wyc) % wyc;return c;}
}A, B;
void Counting(ll g)
{while(g){if (g&1) A = A * B;B = B * B;g>>=1;}
}
int main()
{scanf("%lld%lld", &n, &k);B.n = B.m = A.m = n + 1;A.n = 1;for (int i = 1; i <= n + 1; ++i){scanf("%lld", &B.a[i][n]);//前n个数乘上对应的aif (i < n) B.a[i + 1][i] = 1;//等于下一个}B.a[n + 1][n + 1] = 1;//最后一个afor (int i = 1; i <= n; ++i)scanf("%lld", &A.a[1][i]);A.a[1][n + 1] = 1;Counting(k);printf("%lld", A.a[1][1]);return 0;
}