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
02-11 00:52