Our problem is to obtain as persimmon:
\ [\ sum_ I = {0}} ^ {n-NK C_ {}} ^ {R & lt IK + \]
Consider k and r very small, we can not cut it from here?
If you notice, the number of all combinations of above numbers \ (\% k == r \) , then it is not possible from \ (DP \) start?
It is with the above properties, we can get violent \ (DP \) :
Consider the number of meaningful combinations are selected in a number n m, then we can set \ (dp [i] [j ] \) represents the i-th element, selected from the \ (m \% k == j \) the number of programs
Transfer can be used \ (dp [i] [j ] = dp [i - 1] [j] + dp [i - 1] [j - 1] \) , and according to your European gas, you can get \ ( 45-70 \) score points
For space reasons, the violence code with the rolling array; Due to the length of the article reasons, eliminating the need for some of the violence of code unnecessary things
\(Brute:\)
#define rep(i, s, t) for(re int i = s; i <= t; ++ i)
#define drep(i, s, t) for(re int i = t; i >= s; -- i)
int n, m, p, r, dp[55];
int main() {
n = read(), p = read(), m = read(), r = read(), dp[0] = 1;
rep(i, 1, n * m) {
int pax = dp[m - 1];
drep(j, 1, m - 1) dp[j] = (dp[j - 1] + dp[j]) % p;
dp[0] = (dp[0] + pax) % p;
}
printf("%d", dp[r]);
return 0;
}
So we can also how to optimize it?
Considering the \ (N * K \) reached \ (5 * 10 ^ {10} \) , we consider matrix optimization:
From how we \ (dp [i - 1] [0 ...... m-1] \) launched \ (dp [i] [0 ...... m-1] \) it?
Only need to construct a \ (50 * 50 \) of the matrix, the first row of the first column and the last column \ (1 \) , the rest of the \ (I \) row \ (I \) column and \ ( i-1 \) as 1, others are \ (0 \) , the problem will be solved
Note that the initialization of the matrix can not be directly \ (= 1 \) , to consider \ (k = 1 \) case
\(Code:\)
#include<bits/stdc++.h>
using namespace std;
#define int long long
int read() {
int x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
return x * f;
}
#define rep(i, s, t) for(int i = s; i <= t; ++ i)
int n, m, p, r;
struct Martix {
int a[55][55];
void Init() { rep(i, 1, m) a[i][i] = 1; }
void Mem() { memset(a, 0, sizeof(a)); }
}Ans, Base;
Martix Mul(Martix a, Martix b) {
Martix c; c.Mem();
rep(i, 1, m) rep(j, 1, m) rep(k, 1, m) c.a[i][j] = (c.a[i][j] + a.a[i][k] * b.a[k][j] % p) % p;
return c;
}
Martix Pow(Martix a, int b) {
Martix R; R.Mem(), R.Init();
while(b) {
if(b & 1) R = Mul(R, a);
a = Mul(a, a), b >>= 1;
}
return R;
}
signed main() {
n = read(), p = read(), m = read(), r = read();
++ Base.a[1][1], ++ Base.a[1][m], ++ Ans.a[1][1];
rep(i, 2, m) ++ Base.a[i][i], ++ Base.a[i][i - 1];
Ans = Mul(Ans, Pow(Base, n * m));
printf("%lld", Ans.a[1][1 + r]);
return 0;
}