实际上是水水题叻,先把朴素DP方程写出来,发现$dp[i]$实际上是$dp[i-k]-dp[i-1]$的和,而看数据范围,我们实际上是要快速地求得这段的和,突然就意识到是矩阵快速幂叻。
构建矩阵什么的还是很简单滴,主要就是练一练手。
(还有就是水一水blog!换个字体,换个心情!
(快速乘是在模数很大时要用,避免超long long
#include<bits/stdc++.h> using namespace std; #define LL long long #define mod 7777777 LL k, n, dp[11]; struct Matrix { LL w[11][11]; } base; struct Node { LL w[11][2]; } pool; Matrix Cheng(Matrix a, Matrix b) { Matrix ans; for(int i = 1; i <= k; i ++) for(int j = 1; j <= k; j ++) ans.w[i][j] = 0; for(int i = 1; i <= k; i ++) for(int j = 1; j <= k; j ++) for(int p = 1; p <= k; p ++) ans.w[i][j] = (ans.w[i][j] + a.w[i][p] * b.w[p][j] % mod) % mod; return ans; } Matrix mpow(Matrix a, LL b) { Matrix ans; for(int i = 1; i <= k; i ++) for(int j = 1; j <= k; j ++) if(i == j) ans.w[i][j] = 1; else ans.w[i][j] = 0; for(; b; b >>= 1, a = Cheng(a, a)) if(b & 1) ans = Cheng(ans, a); return ans; } int main() { freopen("fyfy.in", "r", stdin); freopen("fyfy.out", "w", stdout); scanf("%lld%lld", &k, &n); for(int i = 1; i <= k; i ++) for(int j = 1; j <= k; j ++) base.w[i][j] = 0; for(int i = 1; i <= k; i ++) base.w[1][i] = 1; for(int i = 2; i <= k; i ++) base.w[i][i-1] = 1; dp[0] = 1; for(int i = 1; i <= k; i ++) for(int j = 1; j <= i; j ++) dp[i] = (dp[i] + dp[i-j]) % mod; for(int i = 1; i <= k; i ++) pool.w[i][1] = dp[k-i+1]; base = mpow(base, n-k); LL ans = 0; for(int i = 1; i <= k; i ++) ans = (ans + base.w[1][i] * pool.w[i][1] % mod) % mod; printf("%lld", ans); return 0; }