• [AHOI2009]中国象棋


    题目链接

    很显然可以发现一个结论,每一行或每一列都最多只有两个棋子。

    (f[i][j][k])为算到第(i)行,有(j)列有一个棋子,有(k)列有两个棋子。

    然后转移就很显然了:

    设当前枚举到第(i)行,有(j)列有一个棋子,有(k)列有两个棋子,

    若当前行不放棋子,

    [f[i+1][j][k]+=f[i][j][k]. ]

    若当前行放一个棋子,

    [f[i+1][j+1][k]+=f[i][j][k]*(m-j-k). ]

    [f[i+1][j-1][k+1]+=f[i][j][k]*j. ]

    若当前行放两个棋子,

    [f[i+1][j+2][k]+=f[i][j][k]*inom{m-j-k}{2} ]

    [f[i+1][j][k+1]+=f[i][j][k]*(m-j-k)*j ]

    [f[i+1][j-2][k+2]+=f[i][j][k]*inom{j}{2} ]

    统计答案枚举几行放一个,几行放两个,加起来就好了。

    #include<bits/stdc++.h>
    using namespace std;
    #define read(x) scanf("%lld",&x)
    #define write(x) printf("%lld
    ",x)
    #define int long long
    #define maxn 105
    #define p 9999973
    int f[maxn][maxn][maxn],n,m;
    int calc(int x){return x*(x-1)/2;}
    signed main(){
        read(n),read(m);f[0][0][0]=1;
        for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++)
            for(int k=0;j+k<=m;k++)
            if(f[i][j][k]){
                f[i+1][j][k]=(f[i+1][j][k]+f[i][j][k])%p;
                if(m-j-k>=1) f[i+1][j+1][k]=(f[i+1][j+1][k]+f[i][j][k]*(m-j-k))%p;
                if(j>=1) f[i+1][j-1][k+1]=(f[i+1][j-1][k+1]+f[i][j][k]*j)%p;
                if(m-j-k>=2) f[i+1][j+2][k]=(f[i+1][j+2][k]+f[i][j][k]*calc(m-j-k))%p;
                if(m-j-k>=1&&j>=1) f[i+1][j][k+1]=(f[i+1][j][k+1]+f[i][j][k]*(m-j-k)*j)%p;
                if(j>=2) f[i+1][j-2][k+2]=(f[i+1][j-2][k+2]+f[i][j][k]*calc(j))%p;
                //printf("%lld %lld %lld ",i,j,k);write(f[i][j][k]);
            }
        int ans=0;
        for(int i=0;i<=m;i++)
        for(int j=0;j+i<=m;j++)
            (ans+=f[n][i][j])%=p;
        write(ans);
        return 0;
    }
    
    
  • 相关阅读:
    作业3
    学习进度
    作业2
    介绍自己,并介绍github注册过程和初步使用
    mysql显示中文乱码问题解决
    数学能力测试
    C++ Primer总结
    shell脚本
    完全二叉树
    test命令的测试功能
  • 原文地址:https://www.cnblogs.com/hbyer/p/9853131.html
Copyright © 2020-2023  润新知