CF1228E Another Filling the Grid


Description

題目鏈接

\(k\) 個數填進 \(n\times n\) 的網格中,要求每行每列的最小值均為 \(1\) ,求合法方案數對 \(10^9+7\) 取模的結果

\(1\le n\le 250,1\le k\le 10^9\)

Solution

看着標簽是 \(\text{combinatorics}\)\(\text{dp}\) 就看了看題目......

考慮從左向右 \(\text{dp}\) ,每列至少有一個 \(1\) ,同時考慮行的情況。對於某一列如果填完了 \(1\) ,那剩下的位置直接隨便填非 \(1\) 的數就行了,設 \(dp_{i,j}\) 表示到了第 \(i\) 列,還有 \(j\) 行沒有填 \(1\) 的方案數,方程就是

\[dp_{i,j}=dp_{i-1,j}(k-1)^j(k^{n-j}-(k-1)^{n-j})+\sum\limits_{p=1}^{n-j}\dbinom{j+p}{p}dp_{i-1,j+p}k^{n-j-p}(k-1)^j \]

其中 \(k^{n-j}-(k-1)^{n-j}\) 是為了保證這一列至少有一個 \(1\)

復雜度 \(O(n^3)\)

代碼如下:

#include<cstdio>
#include<iostream>
using namespace std;
const int N=3e2+10;
const int mod=1e9+7;
int n,k,dp[N][N],c[N][N],bin[N],bin2[N];
inline void Add(int &x,int y){x+=y;x-=x>=mod? mod:0;}
inline int Minus(int x){x+=x<0? mod:0;return x;}
inline int MOD(int x){x-=x>=mod? mod:0;return x;}
inline void Preprocess(){
	for(register int i=0;i<=n;i++){
		c[i][0]=1;
		for(register int j=1;j<=i;j++)
			c[i][j]=MOD(c[i-1][j]+c[i-1][j-1]);
	}
	bin[0]=1;for(register int i=1;i<=n;i++)bin[i]=1ll*bin[i-1]*k%mod;
	bin2[0]=1;for(register int i=1;i<=n;i++)bin2[i]=1ll*bin2[i-1]*(k-1)%mod;
}
int main(){
	scanf("%d%d",&n,&k);Preprocess();dp[0][n]=1;
	for(register int i=1;i<=n;i++)
		for(register int j=0;j<=n;j++){
			Add(dp[i][j],1ll*dp[i-1][j]*bin2[j]%mod*(Minus(bin[n-j]-bin2[n-j]))%mod);
			for(register int p=1;p<=n-j;p++)
				Add(dp[i][j],1ll*c[j+p][p]*dp[i-1][j+p]%mod*bin[n-j-p]%mod*bin2[j]%mod);
		}
	printf("%d\n",dp[n][0]);
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM