题意
构造一个 H × W H \times W H×W的矩阵,满足一下条件
- 所有元素为整数,且属于 [ − 1 0 9 , 1 0 9 ] [-10^9,10^9] [−109,109]
- 所有元素和为正数
- 对每个 h × w h \times w h×w的子矩阵,它的元素和为负数
题解
根据样例,最朴素的想法即为,给满足
x
m
o
d
h
=
0
x\ mod\ h=0
x mod h=0且
y
m
o
d
w
=
0
y\ mod\ w=0
y mod w=0的位置
(
x
,
y
)
(x,y)
(x,y)标为
−
h
w
-hw
−hw,其余的全部标为
1
1
1
但是有反例
对于
1
×
4
1\times 4
1×4的矩阵,
1
×
3
1\times 3
1×3的子矩阵,会被标为
1
1
−
3
1
\begin{matrix} 1&1&-3&1 \end{matrix}
11−31不合法,可以标为
2
2
−
5
2
\begin{matrix} 2&2&-5&2 \end{matrix}
22−52
考虑改进这个方法,将普通的位置标为 k k k, x m o d h = 0 x\ mod\ h=0 x mod h=0且 y m o d w = 0 y\ mod\ w=0 y mod w=0的位置 ( x , y ) (x,y) (x,y)标为 − k ( h w − 1 ) − 1 -k(hw-1)-1 −k(hw−1)−1,子矩阵的和即为-1,若能找到k,则就有解。
可以证明当 H m o d h = 0 H\ mod\ h=0 H mod h=0且 W m o d w = 0 W\ mod\ w=0 W mod w=0时,无解,此时可以把 H × W H\times W H×W的矩阵恰好分为整数个 h × w h\times w h×w子矩阵,而每个子矩阵为负数,则整个原矩阵不可能和为正数。
如果不满足以上条件,则原矩阵切成若干子矩阵后,还剩一些边角料,边角料每一格值为 k k k,只要使 k k k足够大,一定能抵消掉前面子矩阵得到的很多-1,所以k越大越好。
实现时直接把k卡到最大即可。
代码
#include<cstdio>
const int MAXN=505;
int H,W,h,w;
int arr[MAXN][MAXN];
int main()
{
scanf("%d%d%d%d",&H,&W,&h,&w);
if(h==1&&w==1)
{
puts("No");
return 0;
}
long long sum=0;
int k=999999999/(h*w-1);
{
sum=0;
for(int i=1;i<=H;i++)
for(int j=1;j<=W;j++)
{
if(i%h==0&&j%w==0)
arr[i][j]=-k*(h*w-1)-1;
else
arr[i][j]=k;
sum+=arr[i][j];
}
if(sum>0)
{
puts("Yes");
for(int i=1;i<=H;i++)
{
for(int j=1;j<=W;j++)
printf("%d ",arr[i][j]);
puts("");
}
return 0;
}
}
puts("No");
return 0;
}