P3746 [[six provinces exam 2017] the number of combinations Problem

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;
}

Guess you like

Origin www.cnblogs.com/bcoier/p/11774632.html