題目鏈接: https://codeforces.com/contest/1228/problem/E
題意:
你現在有個 的矩陣,現在要你給每個格子填上一個數字 ,並且要求每一行以及每一列的最小值是 ,問你有多少種填數字的方法。
做法:
只會 的做法,果然還是太菜了。。 的做法表示沒弄懂…先寫下三次方的做法…
合法代表枚舉到第 列時,仍有 行還沒有符合條件的方法種數。
可以從兩種情況轉移過來,① 表示沒有加進新的邊,② ,表示有在新的行上增加 。
爲什麼要這樣把兩種情況分開呢,因爲如果有在新的行上增加 的話,原來已經滿足條件的行就無所謂是不是一定有 了,而如果沒有新增加的話,就必須滿足原來的行中至少有一行有 ,這樣才能滿足在這一列的時候列合法的情況。
① 表示,未滿足的原來的 行中可以任意取除了 以外的值,而滿足條件的 行除了不能全部取非 值以外任意取。
② 表示,假設我們從原來的值爲 時轉移過來,要從中選 個填上 , 行依舊是可以取任意非 的值,除了這 行之外的行可以任意取。(注意這裏是可以任意取,原因上面說過了)。
最後的 就是我們要的答案。
代碼
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i = (int)a;i<=(int)b;i++)
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=255;
ll dp[maxn][maxn],k,C[maxn][maxn];
ll n,qk[maxn],qk1[maxn];
ll quick(ll a,ll b){
ll ans=1;
while(b){
ans=ans*a%mod;
a=a*a%mod;
b/=2;
}
return ans;
}
void init(){
rep(i,0,251) C[i][0]=1;
rep(i,1,251){
rep(j,1,i){
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
}
qk[0]=qk1[0]=1;
rep(i,1,251) {
qk[i]=qk[i-1]*k%mod,qk1[i]=qk1[i-1]*(k-1ll)%mod;
}
}
int main(){
scanf("%lld%lld",&n,&k);
init();
dp[0][n]=1;
rep(i,1,n){
rep(j,0,n){
dp[i][j]=dp[i-1][j]*qk1[j]%mod*((qk[n-j]-qk1[n-j]+mod)%mod)%mod;
rep(p,j+1,n){
dp[i][j]=(dp[i][j]+dp[i-1][p]*C[p][p-j]%mod*qk1[j]%mod*qk[n-p]%mod)%mod;
}
}
}
printf("%lld\n",dp[n][0]);
return 0;
}