【矩阵加速】[SPOJ SEQ]Recursive Sequence
题目描述
Sequence (
where
Input
On the first row there is the number C of test cases (equal to about 1000).
Each test contains four lines:
k - number of elements of (c) and (b) (1 <= k <= 10)
b1,…,bk - k natural numbers where 0 <= bj <=
c1,…,ck - k natural numbers where 0 <= cj <=
n - natural number (1 <= n <=
Output
Exactly C lines, one for each test case: an modulo
Example
Input:
3
3
5 8 2
32 54 6
2
3
1 2 3
4 5 6
6
3
24 354 6
56 57 465
98765432
Output:
8
714
257599514
题目分析
矩阵加速裸题
代码
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 4;
const long long MOD = 1e9;
struct Matrix {
long long Ma[MAXN+10][MAXN+10];
int n, m;
void Clear(int u, int un, int um){
n = un, m = um;
for(int i=1;i<=un;i++)
for(int j=1;j<=um;j++)
Ma[i][j] = 0;
if(u) for(int i=1;i<=un;i++)
Ma[i][i] = 1;
}
Matrix operator* (const Matrix& ma) {
Matrix ret ;
ret.Clear(0, n, m);
for(int i=1;i<=n;i++){
for(int j=1;j<=ma.m;j++){
for(int k=1;k<=ma.n;k++){
ret.Ma[i][j] += Ma[i][k] * ma.Ma[k][j];
ret.Ma[i][j] %= MOD;
}
}
}
return ret;
}
};
Matrix Mpow(Matrix m, int p){
Matrix ret;
if(p == 0){
ret.Clear(1, 2, 2);
return ret;
}else if(p == 1) return m;
ret = Mpow(m, p/2);
if(p%2 == 0) return ret * ret;
return (ret * ret) * m;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
Matrix str, _base;
int n;
scanf("%d", &n);
str.Clear(0, n, n);
_base.Clear(0, n, n);
for(int i=1;i<=n;i++) scanf("%lld", &_base.Ma[1][n-i+1]);
for(int i=1;i<=n;i++){
scanf("%lld", &str.Ma[i][1]);
str.Ma[i][i+1] = 1;
}
int k;
scanf("%d", &k);
if(k <= n) printf("%lld\n", _base.Ma[1][n-k+1]);
else{
int ps = k - n;
Matrix ans = Mpow(str, ps);
long long tans = 0;
for(int i=1;i<=n;i++)
tans += (_base.Ma[1][i] * ans.Ma[i][1])%MOD;
printf("%lld\n", (tans%MOD+MOD)%MOD);
}
}
return 0;
}