您的位置:首页 > 其它

【NOIP2014模拟10.25A组】放棋子

2017-01-21 07:36 330 查看

Description



Solution

首先要保证每行每列至少要有一个,那么就容斥一下,枚举有多少行或列没有选。

因为枚举选不选行和列是相对独立的,那么假设枚举了i行,j列,那么要知道容斥系数(−1)(i+j)。

然后枚举i,j之后,需要知道选出来的方案数Cin∗Cjm

然后在剩下的行中随便搞,有两种方案:1、可以不填,2、不能不填

fji表示吧i个球放入j个桶里面,必须每个桶非空(第二类斯特林数)

f[i][j]=f[i−1][j−1]+f[i−1][j]∗j

1、(c+1)!fc+1(n−i)(m−j)加上一个c+1的颜色(空格),然后(c+1)中颜色再全排列。

2、c!fc(n−i)(m−j)原来的c种颜色,然后再全排列。

最后答案就是

∑i=0n∑j=0mCin∗Cjm∗((c+1)!fc+1(n−i)(m−j)+c!fc(n−i)(m−j))

Code

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=403,mo=1e9+7;
ll i,j,k,l,t,n,m,ans,c,fu;
ll fact[maxn],ni[maxn];
int f[maxn*maxn][maxn];
ll qsm(ll x,ll y){
ll z=1;
for(;y;y/=2,x=x*x%mo)if(y&1)z=z*x%mo;
return z;
}
ll cc(ll x,ll y){return fact[x]*ni[y]%mo*ni[x-y]%mo;}
int main(){
fact[0]=ni[0]=1;
fo(i,1,400)fact[i]=fact[i-1]*i%mo;ni[400]=qsm(fact[400],mo-2);
fod(i,399,1)ni[i]=ni[i+1]*(i+1)%mo;
scanf("%d%d%d",&n,&m,&c);
f[0][0]=1;
fo(i,1,n*m){
fo(j,1,min(c+1,i)){
f[i][j]=(ll)(f[i-1][j-1]+f[i-1][j]*j%mo)%mo;
}
}
fo(i,0,n){
fo(j,0,m){
fu=((i+j)%2)?-1:1;
ans=(ans+cc(n,i)*cc(m,j)%mo*fu*(f[(n-i)*(m-j)][c+1]*fact[c+1]%mo+f[(n-i)*(m-j)][c]*fact[c]%mo)%mo)%mo;
}
}
ans=(ans+mo)%mo;
printf("%lld\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: