[JSOI2015]染色问题
做题日期:2020.11.03
有一个的矩阵,有种颜色,现在要把这种颜色全部涂在矩阵的格子中,要求每一行、每一列都至少得有一格被染色,每一种颜色都至少得涂一格。问有多少种涂色方案。
2 2 3
60
容斥原理
题目中含有多种限制条件,考虑容斥原理。首先枚举一共最多有种颜色涂在了矩阵中,设其答案为,则最终答案为:
对于每一个,可以考虑二次容斥,枚举有列涂颜色。其中即为种颜色(可以不涂)涂到列的方案数(最后减去全不涂颜色的方案)。即:
最后预处理组合数,使用快速幂就可以在的复杂度内求出答案。
#include<cstdio> #include<iomanip> using namespace std; typedef long long ll; const int N=4e2+50; const ll MOD=1000000007; ll f[N]; ll C[N][N];//组合数 int n,m,c; inline void Calc()//预处理组合数 { for(int i=0;i<=400;i++) C[i][0]=1; for(int i=1;i<=400;i++){ for(int j=1;j<=i;j++){ C[i][j]=C[i-1][j-1]+C[i-1][j]; C[i][j]%=MOD; } } } inline ll Fast_Pow(ll a,ll b,ll p)//快速幂 { ll ans=1,base=a; while(b>0){ if(b&1){ ans*=base; ans%=p; } base*=base; base%=p; b>>=1; } return ans; } inline ll Work(int x)//二次容斥求f[x] { ll k=1; ll res=0; ll tmp=1; for(int j=1;j<=m;j++){ if((m-j)%2==0) k=1; else k=-1; tmp*=(ll)x+1; tmp%=MOD; res+=k*C[m][j]*Fast_Pow((tmp-1+MOD)%MOD,(ll)n,MOD); res=(res+MOD)%MOD; } return res; } int main() { scanf("%d%d%d",&n,&m,&c); Calc(); ll k=1; ll ans=0; for(int i=1;i<=c;i++){ if((c-i)%2==0) k=1;//判断当前方案是容是斥 else k=-1; ans+=k*C[c][i]*Work(i); ans=(ans+MOD)%MOD;//ans可能为负数,应当加MOD后%MOD } printf("%lld\n",ans); return 0; }
本文作者:lxzy
本文链接:https://www.cnblogs.com/Unlimited-Chan/p/14026662.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步