【题目链接】
【思路要点】
- 原问题可等价于在\(Nk\)个物品中选出\(pk+r(p\in Z)\)个的方案数。
- 矩阵乘法即可,时间复杂度\(O(k^3LogN)\)。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXLOG = 63; const int MAXN = 55; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int n, P, m, r; int vec[1][MAXN], tmp[1][MAXN]; int matrix[MAXLOG][MAXN][MAXN]; int main() { read(n), read(P), read(m), read(r); for (int i = 0; i < m; i++) { matrix[0][i][i]++; matrix[0][i][(i + 1) % m]++; } for (int p = 1; p < MAXLOG; p++) for (int i = 0; i < m; i++) for (int j = 0; j < m; j++) for (int k = 0; k < m; k++) matrix[p][i][j] = (matrix[p][i][j] + 1ll * matrix[p - 1][i][k] * matrix[p - 1][k][j]) % P; long long N = 1ll * n * m; vec[0][0] = 1; for (int p = 0; p < MAXLOG; p++) { long long bit = 1ll << p; if (N & bit) { memset(tmp, 0, sizeof(tmp)); for (int i = 0; i <= 0; i++) for (int j = 0; j < m; j++) for (int k = 0; k < m; k++) tmp[i][j] = (tmp[i][j] + 1ll * vec[i][k] * matrix[p][k][j]) % P; memcpy(vec, tmp, sizeof(tmp)); } } writeln(vec[0][r]); return 0; }