[杂题]queen Solution

本文探讨了在大规模矩阵中放置皇后,使它们能够互相攻击的算法策略。针对不同皇后数量,提出了一系列优化计算方法,包括利用组合数学原理简化计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:在n×mn\times mn×m的矩阵上面放kkk个皇后使得所有皇后都能互相攻击。不同于正常打法的一点是这里面的皇后能无视阻挡攻击。
这里面的n,mn,mn,mkkk的范围都极大无比,不可能考虑枚举。
考虑到一个皇后瞄准的位置,想让所有的皇后互相攻击,按照皇后的攻击方式来看:如果kkk达到666或更高,那么显然只能让所有皇后都在一条直线上。所以就只需要考虑k≤5k\leq5k5的时候怎么做。
k=1k=1k=1
直接输出矩阵大小即可。
k=2k=2k=2
k>5k>5k>5的时候的放置方法一致。
考虑横向放置,答案就是n×∑i=km(im)n\times \sum^m_{i=k}{i\choose m}n×i=km(mi)
竖向放置类似。
斜向呢?斜着看的话长度应该是分三段排布:

  • k,k+1,k+2……k,k+1,k+2……k,k+1,k+2直到min⁡(n,m)\min(n,m)min(n,m)
  • min⁡(n,m),min⁡(n,m),……\min(n,m),\min(n,m),……min(n,m),min(n,m),这样max⁡(n,m)−min⁡(n,m)+1\max(n,m)-\min(n,m)+1max(n,m)min(n,m)+1
  • min⁡(n,m),min⁡(n,m)−1,min⁡(n,m)−2,……\min(n,m),\min(n,m)-1,\min(n,m)-2,……min(n,m),min(n,m)1,min(n,m)2,这样直到kkk
    剩下的全部是无效段。
    如何计算?考虑上指标求和:(1n)+(2n)+(3n)+……+(mn)=(m+1n+1){1\choose n}+{2\choose n}+{3\choose n}+……+{m\choose n}={m+1\choose n+1}(n1)+(n2)+(n3)++(nm)=(n+1m+1),利用该公式即可。
    k=3k=3k=3
    相对于第二种情况只多了两种特殊的情况:
    在这里插入图片描述
    如何计算?最原始的方法:枚举右下角。
    ∑i=1n∑jmmin⁡(i,j)−1 \sum^n_{i=1}\sum^m_j\min(i,j)-1 i=1njmmin(i,j)1
    考虑如何优化?
    还是上指标求和。
    把矩阵打表打出来看看。
    [00000000011111110122222201233333012344440123455501234566] \begin{bmatrix}0&0&0&0&0&0&0&0\\ 0&1&1&1&1&1&1&1\\ 0&1&2&2&2&2&2&2\\ 0&1&2&3&3&3&3&3\\ 0&1&2&3&4&4&4&4\\ 0&1&2&3&4&5&5&5\\ 0&1 &2&3&4&5&6&6\end{bmatrix} 00000000111111012222201233330123444012345501234560123456
    考虑这个怎么计算?除去没用的000,发现剩下的东西可以看做两个三角形叠在一起加上一个小矩形,这些都是可以简单算出来的。
    利用上指标求和即可:2×(n+13)+(m−n−1)×n×(n−1)22\times {n+1\choose3}+\dfrac{(m-n-1)\times n\times(n-1)}{2}2×(3n+1)+2(mn1)×n×(n1)(假设n<mn<mn<m
    考虑一下翻转,结果乘个444即可。
    另一种情况:
    ∑i=1n∑j=1mmin⁡(i−1,j−12) \sum^{n}_{i=1}\sum^{m}_{j=1}\min(i-1,\frac{j-1}{2}) i=1nj=1mmin(i1,2j1)
    这种情况也类似。
    [0000000001111100112220011223] \begin{bmatrix}0&0&0&0&0&0&0\\ 0&0&1&1&1&1&1\\0&0&1&1&2&2&2\\0&0&1&1&2&2&3\end{bmatrix} 0000000001110111012201220123
    考虑压缩一下列,然后再额外算一下最后一列即可。
    式子和上面类似。
    考虑k=4k=4k=4
    多了以下方案:
    在这里插入图片描述
    第一种和k=3k=3k=3第二种无异。
    第二种和第三种都可以看作长度为奇数的正方形。忽略长度为111的即可。
    矩阵内部怎么数奇数正方形个数?
    假设n<mn<mn<m
    按照nnn的奇偶性推算。
    奇数:
    (n−2)×(m−2)+(n−4)×(m−4)+……+(n−(n−1))+(m−(n−1))=(n−1)2×n×m−n2−14×(n+m)+(n−1)×n×(n+1)6 (n-2)\times (m-2)+(n-4)\times (m-4)+……+(n-(n-1))+(m-(n-1)) \\ =\dfrac{(n-1)}{2}\times n\times m-\dfrac{n^2-1}{4}\times (n+m)+\dfrac{(n-1)\times n\times (n+1)}{6} (n2)×(m2)+(n4)×(m4)++(n(n1))+(m(n1))=2(n1)×n×m4n21×(n+m)+6(n1)×n×(n+1)
    偶数:
    (n−2)×(m−2)+(n−4)×(m−4)+……+(n−(n−2))+(m−(n−2))=n2×n×m−n2−2×n4×(n+m)+(n−2)×(n−1)×n6 (n-2)\times (m-2)+(n-4)\times (m-4)+……+(n-(n-2))+(m-(n-2)) \\ =\dfrac{n}{2}\times n\times m-\dfrac{n^2-2\times n}{4}\times (n+m)+\dfrac{(n-2)\times (n-1)\times n}{6} (n2)×(m2)+(n4)×(m4)++(n(n2))+(m(n2))=2n×n×m4n22×n×(n+m)+6(n2)×(n1)×n
    最后就是边长为任意长度的正方形。
    式子:
    (n−1)×n×m−n×(n−1)2×(n+m)+n×(n−1)×(2×n−1)6 (n-1)\times n\times m-\dfrac{n\times (n-1)}{2}\times(n+m)+\dfrac{n\times (n-1)\times (2\times n-1)}{6} (n1)×n×m2n×(n1)×(n+m)+6n×(n1)×(2×n1)
    k=5k=5k=5
    只有两种情况。
    在这里插入图片描述
    其实早已解决。
    就是找矩形内的奇数正方形。
    code:code:code:
#include <bits/stdc++.h>
#define int long long
#define regi register long long
#define mod 300007
int q,n,m,k;
int jc[1000001],inv[1000001];
inline int read(){
    int r=0,w=0,c;
    for(;!isdigit(c=getchar());r=c);
    for(w=c^48;isdigit(c=getchar());w=w*10+(c^48));
    return r^45?w:-w;
 }
inline long long add(long long x,long long y){
	x%=mod;
	y%=mod;
	return (x+=y)>=mod?x-mod:x;
}
inline long long addself(long long &x,long long y){                                                                                                                                                                               
	return x=add(x,y);
}
inline long long dec(long long x,long long y){
	x%=mod;
	y%=mod;                                                                                                                                                                                                                                                                                                                                                                                          
	return (x-=y)<0?x+mod:x;
}
inline long long decself(long long &x,long long y){
	return x=dec(x,y);                                                                                                                                                                                      
}                                                                                                                                                                               
inline long long mul(long long x,long long y){                                                                                                                                                                               
	x%=mod;
	y%=mod;                                                                                                                                                                               
	return x*y%mod;
}
inline long long mulself(long long &x,long long y){
	return x=mul(x,y);
}                                                                                                                                                                               
inline long long C(long long x,long long y){
	if(!x)
	  return 1;
	if(y<x)
		return 0;                                                                               
		                                                                                                
	if(x<mod&&y<mod)
	  return mul(jc[y],mul(inv[x],inv[y-x]));
	if(y>=mod||x>=mod)
	  return mul(C(x%mod,y%mod),C(x/mod,y/mod));
}
inline long long ksm(long long x,long long y,long long z=1){
	for(;y;mulself(z,y&1?x:1),y>>=1,mulself(x,x));
	return z%mod;
}
inline long long solve1(){
	long long ans=0;
	addself(ans,add(mul(n,C(k,m)),mul(m,C(k,n))));
	addself(ans,add(mul(mul(2,(std::max(n,m)-std::min(n,m)+1)),C(k,std::min(n,m))),mul(4,C(k+1,std::min(n,m)))));
	return ans;
}
inline long long matrix(int x,int y){
	if(x>y)
	  std::swap(x,y);
	return add(mul(2,C(3,x+1)),mul(y-x-1+mod,mul(x,mul(x-1,inv[2]))));
}
inline long long matrixt(int x,int y){
	if(x>y)
	  std::swap(x,y);
	return add(mul(2,add(matrix(n,m/2),matrix(n,m/2+m%2))),mul(2,add(matrix(m,n/2),matrix(m,n/2+n%2))));
}
inline long long odd_square(int x,int y){
	if(x>y)
	  std::swap(x,y);
	long long ans=0;
	if(x&1){
		addself(ans,mul(mul(x-1,ksm(2,mod-2)),mul(x,y)));
		decself(ans,mul(mul(dec(mul(x,x),1),ksm(4,mod-2)),add(x,y)));
		addself(ans,mul(mul(x,mul(dec(x,1),add(x,1))),ksm(6,mod-2)));
	}
	else{
		addself(ans,mul(mul(dec(x,2),ksm(2,mod-2)),mul(x,y)));
		decself(ans,mul(mul(mul(dec(x,2),x),ksm(4,mod-2)),add(x,y)));
	  addself(ans,mul(mul(x,mul(dec(x,1),dec(x,2))),ksm(6,mod-2)));
	}
	return ans;
}
inline long long all_square(int x,int y){ 
	if(x>y)
	  std::swap(x,y);
	long long ans=mul(mul(dec(x,1),x),y);
	decself(ans,mul(mul(mul(x,dec(x,1)),ksm(2,mod-2)),add(x,y)));
	addself(ans,mul(mul(x,mul(dec(x,1),dec(mul(2,x),1))),ksm(6,mod-2)));
	return ans;
}
inline long long Solve3(){
	if(k!=3)
	  return 0;
	long long ans=0;
	addself(ans,mul(4,matrix(n,m)));
  addself(ans,matrixt(n,m));
	return ans;
}
inline long long Solve4(){
	if(k!=4)
	  return 0;
	long long ans=0;
	addself(ans,matrixt(n,m));
	addself(ans,mul(5,odd_square(n,m)));
	addself(ans,all_square(n,m));
	return ans;
}
inline long long Solve5(){
	if(k!=5)
	  return 0;
	long long ans=mul(2,odd_square(n,m));
	return ans;
}
main(){
	jc[0]=1;
	inv[0]=inv[1]=1;
	for(regi i=1;i<=300007;++i)
	  jc[i]=mul(jc[i-1],i);
	for(regi i=2;i<=300007;++i)
	  inv[i]=mul(dec(mod,mod/i),inv[mod%i]);
	for(regi i=2;i<=300007;++i)
	  mulself(inv[i],inv[i-1]);
	q=read();
	while(q--){
		n=read(),m=read(),k=read();
		if(n>m)
		  std::swap(n,m);
		if(k==1)
			printf("%lld\n",mul(n,m));
		else{
			long long ans=solve1();
			addself(ans,add(add(Solve3(),Solve4()),Solve5()));
			printf("%lld\n",ans);
		}
	}
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值