把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

CF1228E Another Filling the Grid【容斥】

题目链接

题目解析

刚开始的思路:我先钦定好,给每行每列一个1,其它随便选,一共n!k(n2n)

但是会有重复,考虑去重。我们还是先给每行每列一个家,但是后面那个不能随便选,我们枚举一些行,一些列,然后让它们随便选,剩下的不能随便选,发现这样也有重复,所以考虑容斥。


看了题解之后发现一个更自然的想法。

我们可以用总方案数减去不合法的方案数。现在考虑不合法的方案长啥样。还是按照钦定多少行/多少列有无1的思路来,我们先减去“有一行/列(第i行/列)没有1,其它随便选”,而这个方案和“有两行/两列/一行一列没有1,其它随便选”有重叠,所以把这样的方案加回来,而上个方案数也有重叠,我们又多加了一次“有三行/三列/两行一列/一行两列没有1,其它随便选”,所以这还是个容斥。

我们把总方案数看成“钦定00列没有1,其它随便选”,于是可以合并在容斥式子里:

ans=i=0nj=0nCniCnj(k1)n(i+j)ijkn2ninj+ij

先无序选出ij列,这ij列上的数除了1以外随便选,剩下的格子可以随便选。

其实还可以用二项式定理优化,还有dp写法,但是咕咕咕~


►Code View

#include<cstdio>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;
#define N 260
#define MOD 1000000007
#define INF 0x3f3f3f3f3f3f3f3f
#define LL long long
LL rd()
{
	LL x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
	return f*x;
}
int n;
LL k;
LL fac[N],inv[N];
LL ksm(LL a,LL b)
{
	LL res=1ll;
	while(b)
	{
		if(b&1) res=res*a%MOD;
		a=a*a%MOD;
		b>>=1;
	}
	return res;
}
void Init()
{
	fac[0]=1,inv[0]=1;
	for(int i=1;i<=N-5;i++)
		fac[i]=fac[i-1]*i%MOD;
	inv[N-5]=ksm(fac[N-5],MOD-2);
	for(int i=N-6;i>=1;i--)
		inv[i]=inv[i+1]*(i+1)%MOD;
}
LL C(int a,int b)
{
	return fac[a]*inv[a-b]%MOD*inv[b]%MOD;
}

int main()
{
	n=rd(),k=rd();
	Init();
	LL ans=0;
	for(int i=0;i<=n;i++)
		for(int j=0;j<=n;j++)
		{
			LL res=C(n,i)*C(n,j)%MOD;
			res=res*ksm(k-1,n*(i+j)-i*j)%MOD*ksm(k,(n-i)*(n-j))%MOD;
			if((i+j)&1) ans=(ans-res+MOD)%MOD;
			else ans=(ans+res)%MOD;//忘了写else可还行 调了20min 
		}
	printf("%lld\n",ans);
	return 0;
}

posted @   Starlight_Glimmer  阅读(74)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示