首页 > 代码库 > UVA - 10870 Recurrences (矩阵快速幂)
UVA - 10870 Recurrences (矩阵快速幂)
Consider recurrent functions ofthe following form:
f(n) = a1 f(n - 1) + a2 f(n - 2) + a3 f(n -3) + ... + ad f(n - d), for n > d.
a1, a2, ..., ad - arbitrary constants.
A famous example is the Fibonacci sequence,defined as: f(1) = 1, f(2) = 1, f(n) = f(n - 1) + f(n - 2). Here d = 2, a1= 1, a2 = 1.
Every such function is completely described byspecifying d (which is called the order of recurrence), values of dcoefficients: a1, a2, ..., ad, and values off(1), f(2), ..., f(d). You‘ll be given these numbers, and two integers n and m.Your program‘s job is to compute f(n) modulo m.
Input
Input file contains several test cases. Each testcase begins with three integers:d, n, m, followed by twosets of d non-negative integers. The first set contains coefficients: a1,a2, ..., ad. The second set gives values of f(1),f(2), ..., f(d).
You can assume that: 1 <= d <= 15, 1<= n <= 231 - 1, 1 <=m <= 46340. Allnumbers in the input will fit in signed 32-bit integer.
Input is terminated by line containing threezeroes instead of d, n, m. Two consecutive test cases are separated by a blankline.
Output
For each test case, print the value of f(n) (mod m)on a separate line. It must be a non-negative integer, less thanm.
SampleInput Output for Sample Input
1 1 100 2 1 2 10 100 1 1 1 1 3 2147483647 12345 12345678 0 12345 1 2 3
0 0 0 | 1 55 423
|
Problem setter: MaxFurlong
Special Thanks: DerekKisman, EPS.
题意:考虑一个递推关系 f[n] = a1*f[n-1] + a2*f[n-2] + .... ad*f[n-d],求f[n] % m
思路:和经典的Fibonacci的递推矩阵构造类似
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> typedef long long ll; using namespace std; const int maxn = 30; int n, m, d; struct Matrix { ll v[maxn][maxn]; Matrix() {} Matrix(int x) { init(); for (int i = 0; i < maxn; i++) v[i][i] = x; } void init() { memset(v, 0, sizeof(v)); } Matrix operator *(Matrix const &b) const { Matrix c; c.init(); for (int i = 0; i < d; i++) for (int j = 0; j < d; j++) for (int k = 0; k < d; k++) c.v[i][j] = (c.v[i][j] + (v[i][k] * b.v[k][j]) % m) % m; return c; } Matrix operator ^(int b) { Matrix tmp = *this, res(1); while (b) { if (b & 1) res = res * tmp; tmp = tmp * tmp; b >>= 1; } return res; } } a, b, res; ll f[maxn]; int main() { while (scanf("%d%d%d", &d, &n, &m) != EOF && n+m+d) { a.init(); b.init(); for (int i = 0; i < d; i++) scanf("%lld", &a.v[0][i]); for (int i = 0; i < d; i++) scanf("%lld", &f[i]); for (int i = 1; i < d; i++) a.v[i][i-1] = 1; if (n == 1) { printf("%lld\n", f[n-1]); continue; } b = a ^ (n-d); ll ans = 0; for (int i = 0; i < d; i++) ans = (ans + (f[d - 1 - i] * b.v[0][i]) % m) % m; printf("%lld\n", ans); } return 0; }
UVA - 10870 Recurrences (矩阵快速幂)