void matrix_exp(const Matrix &m, u64 e, Matrix &r) { if (e == 1) { r = m; return; } Matrix x; if (e % 2 == 0) { matrix_exp(m, e / 2, x); matrix_mul(x, x, r); return; } matrix_exp(m, e-1, x); matrix_mul(x, m, r); }
int main() { choose_table(); int T; scanf("%d", &T); int ncase = 0; while (T--) { scanf("%llu%d", &N, &K); if (N == 1) { printf("Case %d: 1\n", ++ncase); continue; } fill_matrices(); matrix_exp(A, N-1, R); u32 ans = 0; for (int i = 0; i <= K + 1; ++i) ans += R.m[K+1][i]; printf("Case %d: %u\n", ++ncase, ans); } return 0; }
/* fast exponentiation algorithm, not used anymore but could be useful in a primary test */ int* matrix_exp(int n, const int *a, int m, int *r) { /* it would be possible to do one less allocation here at the cost of a memmove() but it would make the code more complicated */ int *sq, *tmp; if (m == 0) return (matrix_make_id(n, r)); if (m == 1) return r; sq = matrix_mult(n, a, a, malloc(n*n*sizeof(int))); if (m % 2 == 0) { matrix_exp(n, sq, m/2, r); } else { tmp = matrix_exp(n, sq, m/2, malloc(n*n*sizeof(int))); matrix_mult(n, a, tmp, r); free(tmp); } free(sq); return r; }