• [CQOI2011] 放棋子


    在一个 (m)(n) 列的棋盘里放一些彩色的棋子,使得每个格子最多放一个棋子,且不同颜色的棋子不能在同一行或者同一列,有多少种方法?

    Solution

    (f[i][j][k]) 表示用前 (k) 种颜色的棋子,占领了 (i)(j) 列的方案数

    (g[i][j][k]) 表示用任意 (k) 个同色棋子占领 (i)(j) 列的方案数,则考虑总方案数 - 实际上有没有被占领的行或列的方案数,则

    [g[i][j][k]=C_{ij}^k-sum_{l=1}^isum_{r=1}^j g[l][r][k]cdot C_i^l C_j^r ]

    于是对 (f[i][j][k]),转移方程为

    [f[i][j][k]=sum_{l=0}^{i-1} sum_{r=0}^{j-1} f[l][r][k-1]cdot g[i-l][j-r][a[k]]cdot C_{n-l}^{i-l} C_{m-r}^{j-r} ]

    注意这个转移当 ((i-l)(j-r) ge a[k]) 时才成立,于是答案为

    [sum_{i=1}^n sum_{j=1}^m f[i][j][c] ]

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 35;
    const int mod = 1e+9+9;
    
    int f[N][N][N],g[N][N][N*N],n,m,c,a[N],C[N*N][N*N];
    
    signed main() {
        ios::sync_with_stdio(false);
        cin>>n>>m>>c;
        C[0][0]=1;
        for(int i=1;i<=1000;i++) {
            C[i][0]=1;
            for(int j=1;j<=i;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
        }
        int mx=0;
        for(int i=1;i<=c;i++) cin>>a[i], mx=max(mx,a[i]);
        f[0][0][0]=1;
        for(signed i=1;i<=n;i++) {
            for(signed j=1;j<=m;j++) {
                for(signed k=1;k<=mx;k++) {
                    int fg=0;
                    for(signed t=1;t<=c;t++) if(a[t]==k) fg=1;
                    if(!fg) continue;
                    g[i][j][k]=C[i*j][k];
                    for(signed l=1;l<=i;l++) {
                        for(signed r=1;r<=j;r++) {
                            if(i==l && j==r) continue;
                            g[i][j][k]=(g[i][j][k]-g[l][r][k]*C[i][l]%mod*C[j][r]%mod+mod)%mod;
                        }
                    }
                }
            }
        }
        for(signed i=1;i<=n;i++) {
            for(signed j=1;j<=m;j++) {
                for(signed k=1;k<=c;k++) {
                    for(signed l=0;l<i;l++) {
                        for(signed r=0;r<j;r++) {
                            if((i-l)*(j-r)>=a[k])
                                (f[i][j][k]+=f[l][r][k-1]*g[i-l][j-r][a[k]]%mod*C[n-l][i-l]%mod*C[m-r][j-r]%mod)%=mod;
                        }
                    }
                }
            }
        }
        int ans=0;
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) (ans+=f[i][j][c])%=mod;
        cout<<ans;
    }
    
    
  • 相关阅读:
    SpringCloud组件---Ribbon
    SpringCloud组件---Eureka
    tomcat及Jetty远程调试debug
    mysql 删除重复数据
    mysql执行SQL语句时报错:[Err] 3
    线程池原理剖析
    上限下限
    线程池Executors、Callable与Future的应用
    spring获取bean(自定义工具类)
    java.util.concurrent.Exchanger应用范例
  • 原文地址:https://www.cnblogs.com/mollnn/p/12643871.html
Copyright © 2020-2023  润新知