FZU_1683
利用递推关系可以构造出下图所示的矩阵,然后用二分矩阵求解就可以了。
由于递推关系的矩阵是固定了,所以不妨先把二分矩阵中用到的递推关系的矩阵的2^x(0<=x<32)次幂预处理出来,这样可以节省一些时间。
#include<stdio.h> #include<string.h> #define MAXD 4 #define D 2009 int N; struct Matrix { int a[MAXD][MAXD]; Matrix() { memset(a, 0, sizeof(a)); } void init() { memset(a, 0, sizeof(a)); a[0][0] = a[0][1] = 1; a[1][1] = 3, a[1][2] = 2, a[1][3] = 7; a[2][1] = 1; a[3][2] = 1; } }mat[40]; Matrix multiply(Matrix &x, Matrix &y) { int i, j, k, ans; Matrix z; for(k = 0; k < 4; k ++) for(i = 0; i < 4; i ++) if(x.a[i][k]) { for(j = 0; j < 4; j ++) if(y.a[k][j]) z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j]) % D; } return z; } void powmod(Matrix &unit, int n) { int cnt = 0; while(n) { if(n & 1) unit = multiply(mat[cnt], unit); n >>= 1, ++ cnt; } } void prepare() { int i; mat[0].init(); for(i = 1; i < 32; i ++) mat[i] = multiply(mat[i - 1], mat[i - 1]); } void solve() { Matrix unit; unit.a[0][0] = 4, unit.a[1][0] = 5, unit.a[2][0] = 3, unit.a[3][0] = 1; powmod(unit, N - 1); printf("%d\n", unit.a[0][0]); } int main() { int t, tt; prepare(); scanf("%d", &t); for(tt = 0; tt < t; tt ++) { scanf("%d", &N); printf("Case %d: ", tt + 1); if(N == 0) printf("1\n"); else solve(); } return 0; }