Loading

CodeForces-232B Table 组合数学 DP

CodeForces-232B Table 组合数学 DP

题意

给定一个大小$N \times M $ 的棋盘

问有多少种方案使得每个$N \times N $ 的区域中恰好有\(k\) 个棋子。

\[N \leq 100,N \leq M \leq 10^{18},K \leq N ^2 \]

分析

显然该棋盘具有周期性的特征,如图示所示,“A+B”区域明显是一个循环块,A = C

这说明可以利用循环的特性计算贡献。

\(dp[i][j]\)表示到第\(i\) 列总共用了\(j\) 个棋子对答案的贡献

我们有转移方程

\[dp[i+1][j+q] = dp[i+1][j+q] + dp[[i][j] \cdot (C_N^q)^{cnt} \]

\(cnt\) 是周期个数,对于\(A\) 部分是\(m/n + 1\) ,其余则是\(m/n\)

代码

int d[111], e[111];
int c[111][111];
int f[111][11111];

int main() {
    int n = readint();
    ll m = readll();
    int k = readint();
    for (int i = 0; i <= n; i++)
        c[i][0] = 1;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= i; j++)
            c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
    for (int j = 0; j <= n; j++) {
        d[j] = quickPower(c[n][j], m / n, MOD);
        e[j] = quickPower(c[n][j], m / n + 1, MOD);
    }
    int mm = m % n;
    f[0][0] = 1;
    for(int i = 0;i < n;i++)
        for(int j = 0;j <= k;j++)
            if (f[i][j]) {
                for (int q = 0; q <= n; q++) {
                    int ft;
                    if (i < mm) ft = e[q];
                    else ft = d[q];
                    f[i + 1][j + q] = (f[i + 1][j + q] + (ll)ft * f[i][j]) % MOD;
                }
            }
    Put(f[n][k]);
}
posted @ 2020-09-12 22:23  MQFLLY  阅读(174)  评论(0编辑  收藏  举报