http://codeforces.com/contest/1228/my 题意:有个nm的矩形 每个格子可以取1-k中的一种数字 问有多少种填法 使得每行每列至少都有一个1 题解:设置dp[i][j] 表示 当前处理到i行有j列为1的方案数
http://codeforces.com/contest/1228/my
题意:有个nm的矩形 每个格子可以取1-k中的一种数字 问有多少种填法 使得每行每列至少都有一个1
题解:设置dp[i][j] 表示 当前处理到i行有j列为1的方案数 然后统计答案贡献即可 注意改行至少取一个1
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<‘=‘<<(x)<<endl) #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=300; const ll mod=1e9+7; ll dp[N][N],mi[N],mi_1[N],C[N][N],n,k; int main() { cin>>n>>k; rep(i,0,n) { C[i][0]=1; rep(j,1,i)C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod; } mi[0]=mi_1[0]=1; rep(i,1,n)mi[i]=mi[i-1]*k%mod,mi_1[i]=mi_1[i-1]*(k-1)%mod; rep(i,1,n)dp[1][i]=C[n][i]*mi_1[n-i]%mod; rep(i,2,n)rep(j,0,n)rep(s,0,j) { dp[i][j]=(dp[i][j]+dp[i-1][s]*C[n-s][j-s]%mod*mi[s]%mod*mi_1[n-j]%mod)%mod; if(j==s)dp[i][j]=(dp[i][j]-mi_1[n]*dp[i-1][s]%mod+mod)%mod;//一定要容斥掉全部非一的方案数 } cout<<dp[n][n]; return 0; }View Code