AtCoder ABC 242 pF. Black and White Rooks 解題心得( 題目 )

解題概念:DP、排列組合

解題方法:在解題之前,先思考一個性質:如果這行有白色的,那就不能有黑色,我們可以先討論個DP[i][j],定義他代表我放了某個顏色的棋子(假設a個)後,(1)可以把他放入一個i*j的長方形,(2)裡面每排每列都有至少一個棋子的方法數,那這個值怎麼求呢?

我們可以用C(i*j,a)代表他,可是顯然DP[i][j]不會等於C(i*j,a),因為有些情況並沒有符合條件(2),所以我們得扣除前面的DP乘上組合數。

我們可在O(N^2M^2)算出表格,但是求出DP能幹嘛呢,我們注意到DP代表他的排列方式,假設我們已經做出兩個表格W、B,則我們可以枚舉W[i][j]、B[k][l]的組合,注意i+k<n,j+l<m都符合!可是怎麼算呢?

我們前面算的DP是正方形,但是我們把它轉成從開始的棋盤選出i列j行,接著剩下的棋盤列行選出k列l行,也就是枚舉i、j、k、l,將所有B[i][j]*B[k][l]*C(N,i)*C(M,j)*C(N-i,k)*C(M-j,l) 加總!!

Java參考程式碼(更好意見可留言於下方,謝謝!):

//Author:En Chi Tsung(欉恩祁)

//Date:2022/03/09

import java.util.*;

import java.io.*;

public class Main {

    public static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));

    public static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));

    public static int ret,rd;

    public static final long p=998244353;

    public static long[] fac=new long[2505];

    public static long[] inv=new long[2505];

    public static long[][] db=new long[55][55];

    public static long[][] dw=new long[55][55];

    public static void main(String[] args) throws Exception{

        final int N=readint();

        final int M=readint();

        final int B=readint();

        final int W=readint();

        init();

        long cnt=0,ans=0;

        for(int i=1;i<=N;i++) {

            for(int j=1;j<=M;j++) {

                cnt=0;

                for(int k=1;k<=i;k++) {

                    for(int l=1;l<=j;l++) {

                        cnt+=(db[k][l]*pi(j,l)%p*pi(i,k))%p;

                        cnt%=p;

                    }

                }

                db[i][j]=per(i,j,B)-cnt+p*10;

                db[i][j]%=p;

            }

        }

        

        for(int i=1;i<=N;i++) {

            for(int j=1;j<=M;j++) {

                dw[i][j]=cnt=0;

                for(int k=1;k<=i;k++) {

                    for(int l=1;l<=j;l++) {

                        cnt+=(dw[k][l]*pi(j,l)%p*pi(i,k))%p;

                        cnt%=p;

                    }

                }

                dw[i][j]=per(i,j,W)-cnt+p*10;

                dw[i][j]%=p;

            }

        }

        

        for(int i=1;i<N;i++) {

            for(int j=1;j<M;j++) {

                for(int k=N-i;k>0;k--) {

                    for(int l=M-j;l>0;l--) {

                        ans+=(db[i][j]*dw[k][l]%p*pi(N,i)%p*pi(M,j)%p*pi(N-i,k)%p*pi(M-j,l)%p);

                        ans%=p;

                    }

                }

            }

        }

        System.out.println(ans);

        

    }


    

    public static long per(int x,int y,int n) {

        if(n>x*y)return 0;

        return fac[x*y]*inv[n]%p*inv[x*y-n]%p;

    }

    

    public static long pi(int m,int n) {

        return fac[m]*inv[n]%p*inv[m-n]%p;

    }

    

    public static void init() {

        fac[0]=1;

        for(int i=1;i<2505;i++) {

            fac[i]=fac[i-1]*i;

            fac[i]%=p;

        }

        for(int i=0;i<2505;i++) {

            inv[i]=fast(fac[i],p-2);

        }

    }

    

    public static long fast(long x,long pw) {

        if(pw<=1) {

            return x;

        }

        if((pw&1)==0) {

            long ret=fast(x,pw>>1);

            return ret*ret%p;


        }

        else {

            long ret=fast(x,pw>>1);

            return ret*ret%p*x%p;

        }

    }


    

    public static int readint() throws Exception{

        ret=0;

        rd=br.read();

        while(rd>47&&rd<58) {

            ret*=10;

            ret+=(rd&15);

            rd=br.read();


        }

        return ret;

    }

}

 

 

 

 

 

arrow
arrow

    En Chi Tsung 發表在 痞客邦 留言(0) 人氣()