【JZOJ4779】鞍点

该博客介绍了如何利用数学和动态规划解决鞍点问题。通过建立f[i][j]矩阵表示含有i个鞍点且最大值为j的矩阵数量,文章详细解释了状态转移方程,并给出了最终的容斥原理公式来求解答案。文章包含问题描述、分析过程及代码实现。
部署运行你感兴趣的模型镜像

description


analysis

  • 数学+DP+DP+DP

  • f[i][j]f[i][j]f[i][j]表示当前至少有iii个鞍点、鞍点的值最大为jjj的矩阵数量

  • 设添加xxx个权值为j+1j+1j+1的鞍点,观察这张图来了解如何转移

  • 绿色的部分已经放好了,对右下角的矩阵没有影响

  • xxxj+1j+1j+1的贡献本身是Cxn−iCxm−i⋅x!C^{n-i}_xC^{m-i}_x·x!CxniCxmix!

  • 对于蓝色的部分,只能放[0,j][0,j][0,j]的数,贡献为jx(n−i)+x(m−i)−x2−xj^{x(n-i)+x(m-i)-x^2-x}jx(ni)+x(mi)x2x

  • 转移方程为f[i+x][j+1]+=f[i][j]⋅Cxn−iCxm−i⋅x!⋅jx(n−i)+x(m−i)−x2−xf[i+x][j+1]+=f[i][j]·C^{n-i}_xC^{m-i}_x·x!·j^{x(n-i)+x(m-i)-x^2-x}f[i+x][j+1]+=f[i][j]CxniCxmix!jx(ni)+x(mi)x2x

  • 对于白色的部分,放什么都可以,转移完以后才乘上贡献为k(n−i)(m−i)k^{(n-i)(m-i)}k(ni)(mi)

  • 最后答案容斥一下,ans=∑i=1min(n,m)(−1)i+1f[i][k]ans=\sum^{min(n,m)}_{i=1}(-1)^{i+1}f[i][k]ans=i=1min(n,m)(1)i+1f[i][k]

  • 111个鞍点的答案减去222个鞍点的情况,再加上333个鞍点的情况……等等


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define MAXN 2005
#define ll long long
#define reg register ll
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define O3 __attribute__((optimize("-O3")))

using namespace std;

ll f[MAXN][MAXN],c[MAXN][MAXN];
ll fac[MAXN*MAXN],pow[11][MAXN*MAXN];
ll n,m,k,mod,ans,temp=1;

O3 inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
O3 int main()
{
	//freopen("T2.in","r",stdin);
	n=read(),m=read(),k=read(),mod=read();
	c[0][0]=fac[0]=pow[0][0]=1;
	if (n>m)swap(n,m);
	fo(i,1,m)
	{
		c[i][0]=1;
		fo(j,1,m)c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
	}
	fo(i,1,n*m)fac[i]=i*fac[i-1]%mod;
	fo(i,1,k)
	{
		pow[i][0]=1;
		fo(j,1,n*m)pow[i][j]=pow[i][j-1]*i%mod;
	}
	f[0][0]=1;
	fo(i,0,n)
	{
		fo(j,0,k-1)
		{
			if (f[i][j]==0)continue;
			fo(x,0,n-i)
			(f[i+x][j+1]+=f[i][j]*c[n-i][x]%mod*c[m-i][x]%mod*fac[x]%mod*pow[j][x*(n+m-2*i)-x*x-x]%mod)%=mod;
		}
	}
	fo(i,1,n)ans=((ans+temp*f[i][k]%mod*pow[k][(n-i)*(m-i)%mod])+mod)%mod,temp*=-1;
	printf("%lld\n",ans);
	return 0;
}

您可能感兴趣的与本文相关的镜像

AutoGPT

AutoGPT

AI应用

AutoGPT于2023年3月30日由游戏公司Significant Gravitas Ltd.的创始人Toran Bruce Richards发布,AutoGPT是一个AI agent(智能体),也是开源的应用程序,结合了GPT-4和GPT-3.5技术,给定自然语言的目标,它将尝试通过将其分解成子任务,并在自动循环中使用互联网和其他工具来实现这一目标

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值