省选测试22

A 送你一道签到题 (Unaccepted)

题目大意 :

  • 咕咕

Code

Show Code

B 神犇 (Unaccepted)

题目大意 :

  • 咕咕

Code

Show Code

C 开挂

题目大意 : 有多少组nm的01矩阵用两个xy的矩阵完全覆盖

  • 枚举01矩阵的最小范围,dp的时候有6维,前4维是4边有没有1,第5维是1不在左上右下的情况里的覆盖范围,第6维是1不在左下右上的情况覆盖范围

  • 因为是枚举的边界,前4维都是必须满足的,而5,6维只要有1就合法

  • 然后就是这题卡常

Code

Show Code
#include <cstdio>
#include <cstring>

using namespace std;
const int M = 998244353;

int n, m, x, y, f[2][64], ans = 1;

void Add(int &x, int y) {
    if ((x += y) >= M) x -= M;
}

int Solve(int n, int m) {
    int k = 0;
    memset(f[k], 0, 64 * 4);
    f[k][0] = 1;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            memset(f[k^=1], 0, 64 * 4);
            for (int s = 0; s < 64; ++s)
                Add(f[k][s], f[k^1][s]), Add(f[k][s|(i==1)<<5|(i==n)<<4|(j==1)<<3|(j==m)<<2|
                (!(i <= x && j <= y) && !(i+x > n && j+y > m)) << 1 | (!(i <= x && j+y > m) && !(i+x > n && j <= y))], f[k^1][s]);
        }
    }
    return (1ll * f[k][60] + f[k][61] + f[k][62]) % M;
}

int main() {
    scanf("%d%d%d%d", &n, &m, &x, &y);
    for (int i = 1; i <= n; ++i)
        for (int j = 1; j <= m; ++j)
            if ((ans += 1ll * (n - i + 1) * (m - j + 1) % M * Solve(i, j) % M) >= M) ans -= M;
    printf("%d
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/shawk/p/14418952.html