求
定义下指标大于上指标时, 二项式系数等于0. (1≤n≤10^9, 0≤r<k≤50, 2≤p≤2^30-1) 小葱发现,
说得太好了! 我考试的时候就忘掉了这一点......TAT
本题也是thu校赛练习赛的题目之一, yp同学教了我一下做法. QAQ
n很大, r,k很小, 看起来像矩阵快速幂. 强行构造递推, 用范德蒙德卷积公式:
(原来只知道
记答案为
发现转移矩阵是循环的, 所以可以只保留第一行 (虽然在本题中不是必须的).
也可以考虑待求和式的组合意义 (见WrongAnswer的博客). 记
同时,
此时, 我们也能看到
typedef long long ll;
const int K = 50;
ll C[K+1][K+1];
int p;
struct Matrix {
ll a[K][K];
Matrix(ll t=0)
{
fill_n(*a, sizeof(a)/sizeof(ll), 0);
rep (i, 0, K) a[i][i] = t;
}
Matrix operator*(const Matrix& o) const
{
Matrix r;
rep (i, 0, K) rep (j, 0, K) rep (k, 0, K)
(r.a[i][j] += a[i][k] * o.a[k][j]) %= p;
return r;
}
friend Matrix pow(Matrix x, int n)
{
Matrix y(1);
for (; n; n >>= 1, x = x*x)
if (n & 1)
y = y * x;
return y;
}
} M;
int main()
{
int n, k, r;
scanf("%d%d%d%d", &n, &p, &k, &r);
rep (i, 0, k+1) {
C[i][0] = 1;
rep (j, 1, i+1)
C[i][j] = (C[i-1][j] + C[i-1][j-1]) % p;
}
M.a[0][0] = 2 % p;
rep (i, 1, k) M.a[0][i] = C[k][i];
rep (i, 1, k) {
M.a[i][0] = M.a[i-1][k-1];
rep (j, 1, k) M.a[i][j] = M.a[i-1][j-1];
}
M = pow(M, n-1);
ll ans = 2 * M.a[0][r] % p;
rep (i, 1, k) (ans += C[k][i] * M.a[i][r]) %= p;
printf("%lld\n", ans);
return 0;
}