B

World Fragments I

https://ac.nowcoder.com/acm/contest/57357/A

BB

[1,n][1, n]的数看作00,将[n+1,2n][n+1, 2n]的数看作11,则任何1010,或者0101都是合法的,只有0000或者1111有可能会不合法,设[i][j][0/1][i][j][0/1]表示考虑了前ii个,第ii个为0/10/1时,共用了jj00的合法方案数,转移方程考虑枚举ii往前是一连串的00或者11,枚举从哪里转移而来,若由f[k][x][y]f[k][x][y]转移而来,那么在[k+1,i][k+1,i]这个区间全是00或者11,考虑合法方案这一段的填的数(从剩余的数中取这个区间长度的数出来)大小是固定的即从大到小或者从小到大放置,考虑到ii位置才不合法,则这一段数除了最小/最大的不能放在ii(否则就合法),其它的都可以,然后令剩下的数按照合法顺序放即可,最后ii后面可以随便放,于是不合法方案就可以算出来了

code

#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn = 605;
int T, n, n2, m;
int fac[maxn];
int c[maxn][maxn];
int f[maxn][maxn][2];
void init ()
{
    fac[0] = c[0][0] = 1;
    for (int i = 1; i <= n2; ++i)	fac[i] = 1ll * fac[i - 1] * i % m;
    for (int i = 1; i <= n2; ++i) {
        c[i][0] = 1;
        for (int j = 1; j <= i; ++j)
            c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % m;
    }
    for (int i = 1; i <= n2; ++i)
        for (int j = 0; j <= n2; ++j)    f[i][j][0] = f[i][j][1] = 0;
}
int main ()
{
    scanf("%d", &T);
while (T--) {
    scanf("%d%d", &n, &m);
    n2 = n << 1;
    init();
    f[0][0][0] = f[0][0][1] = 1;
    int ans = 0;
    for (int i = 1; i <= n2; ++i) {
        for (int j = min(i, n); j >= 0; --j) {
            for (int k = i - 1; k >= 0; --k) {
                int t0 = j - (i - k);
                if (t0 < 0 || t0 > min(k, n))	continue;
                f[i][j][0] += 1ll * f[k][t0][1] * c[n - t0][i - k] % m;
                f[i][j][0] %= m;
                ans += 1ll * f[k][t0][1] * c[n - t0][i - k] % m * (i - k - 1) % m * i % m * fac[n2 - i] % m;
                ans %= m;
            }
            for (int k = i - 1; k >= 0; --k) {
                int t1 = (i - j) - (i - k);
                if (t1 < 0 || t1 > min(n, k))	continue;
                
                f[i][j][1] += 1ll * f[k][j][0] * c[n - t1][i - k] % m;
                f[i][j][1] %= m;
                ans += 1ll * f[k][j][0] * c[n - t1][i - k] % m * (i - k - 1) % m * i % m * fac[n2 - i] % m;
                ans %= m;
            }
        }
    }
    ans += (1ll * f[n2][n][0] * n2 % m + 1ll * f[n2][n][1] * n2 % m) % m;
    ans %= m;
    printf("%d\n", ans);
}
    return 0;
}

全部评论

相关推荐

08-29 07:47
已编辑
莆田学院 Java
路上小荷:小孙,你好,我是由XX幼儿园、XX小学、XX初中、XX高中、XX大***合培养的研究生,想寻找能够陪我一起成长,登上人生巅峰的公司。在公司任职期间公司需要提供免费食宿、百万年薪以及私人医生。预计65岁退休,退休后公司可以求我给新员工讲述奋斗历程
点赞 评论 收藏
分享
12 收藏 评论
分享
牛客网
牛客企业服务