2019.02.09 bzoj4487: [Jsoi2015]染色问题(容斥原理)

传送门
题意简述:
ccc中颜色给一个n∗mn*mnm的方格染色,每个格子可涂可不涂,问最后每行每列都涂过色且ccc中颜色都出现过的方案数。


思路:
fi,j,kf_{i,j,k}fi,j,k表示至少iii行没涂色,至少jjj列没涂色,至少ccc种颜色没涂色的方案数。
于是fi,j,k=CniCmjCck(c−k+1)(n−i)(m−j)f_{i,j,k}=C_n^iC_m^jC_c^k(c-k+1)^{(n-i)(m-j)}fi,j,k=CniCmjCck(ck+1)(ni)(mj)
容斥一下即可。
注意算最后一项的时候每次先预处理。
代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
const int N=405,mod=1e9+7,mod1=1e9+6;
int ans=0,fac[N],ifac[N],n,m,c,a[N],mult[N*N];
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline int C(int n,int m){return mul(mul(fac[n],ifac[m]),ifac[n-m]);}
inline void init(){
	int up=max(n,max(m,c));
	fac[0]=fac[1]=ifac[0]=ifac[1]=1;
	for(ri i=2;i<=up;++i)fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[mod-mod/i*i],mod-mod/i);
	for(ri i=2;i<=up;++i)ifac[i]=mul(ifac[i],ifac[i-1]);
}
int main(){
	freopen("lx.in","r",stdin);
	cin>>n>>m>>c;
	init();
	for(ri k=0,tmp;k<=c;++k){
		mult[0]=1;
		for(ri i=1;i<=n*m;++i)mult[i]=mul(mult[i-1],c-k+1);
		for(ri i=0;i<=n;++i)for(ri j=0;j<=m;++j){
			tmp=mul(mul(C(n,i),C(m,j)),mul(C(c,k),mult[(n-i)*(m-j)]));
			ans=(i+j+k)&1?dec(ans,tmp):add(ans,tmp);
		}
	}
	cout<<ans;
	return 0;
}

转载于:https://www.cnblogs.com/ldxcaicai/p/10367696.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值