UVA 10870 - Recurrences(矩阵高速功率)

UVA 10870 - Recurrences

题目链接

题意:f(n) = a1 f(n - 1) + a2 f(n - 2) + a3 f(n - 3) + ... + ad f(n - d), for n > d.
已知前d项求第n项

思路:矩阵高速幂,相应矩阵为
|a1 a2 a3 ... ad|
|1 0 0 ... 0 0 0|
|0 1 0 ... 0 0 0|
|0 0 1 ... 0 0 0|
|0 0 0 ... 0 0 0|
|0 0 0 ... 1 0 0|
|0 0 0 ... 0 1 0|
|0 0 0 ... 0 0 1|

代码:

#include <stdio.h>
#include <string.h>

const int N = 20;
long long d, n, m, f[N];

struct mat {
	long long n, v[N][N];
	mat(long long n = 0) {
		this->n = n;
   		memset(v, 0, sizeof(v));
   	}
	mat operator * (mat b) {
		mat ans = mat(n);
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				for (int k = 0; k < n; k++) {
					ans.v[i][j] = ((ans.v[i][j] + v[i][k] * b.v[k][j] % m) % m + m) % m;
    			}
   			}
  		}
  		return ans;
 	}
};

mat pow_mod(mat a, long long k) {
	mat ans(a.n);
	for (int i = 0; i < ans.n; i++)
		ans.v[i][i] = 1;
	while (k) {
		if (k&1) ans = ans * a;
		a = a * a;
		k >>= 1;
	}
	return ans;
}

int main() {
	while (~scanf("%lld%lld%lld", &d, &n, &m) && d) {
		mat a = mat(d);
		for (int i = 0; i < d; i++)
			scanf("%lld", &a.v[0][i]);
		for (int i = 1; i < d; i++)
			a.v[i][i - 1] = 1;
		for (int i = 0; i < d; i++)
			scanf("%lld", &f[i]);
		if (n <= d) printf("%lld\n", f[n - 1]);
		else {
			long long ans = 0;
			a = pow_mod(a, n - d); 
			for (int i = 0; i < d; i++)
				ans = (ans + (f[d - i - 1] * a.v[0][i] % m + m)) % m;
  			printf("%lld\n", ans);
  		}
 	}
	return 0;
}


posted @ 2015-06-26 10:38  zfyouxi  阅读(243)  评论(0编辑  收藏  举报