To_Heart—题解——AGC016C
题意
给定 n n n , m m m , h h h , w w w,构造一个 n × m n \times m n×m 的矩阵满足任意一个 h × w h\times w h×w 的子矩阵的和小于 0,总矩阵和大于 0,且每个位置的权值绝对值不超过 1 0 9 10^9 109
题解
很容易发现,我们让每个要求的子矩阵中有一个负数是最优的。所以我们就将 i % h = 0 & j % w = 0 i \% h =0 \& j\%w=0 i%h=0&j%w=0 的点赋值为 − h × w -h\times w −h×w ,其余的点全是 1 就好了。
但是会 WA。我们考虑一组数据 1 3 1 2
会发现我们构造出来的矩阵是 1 -2 1
但是如果我们把赋正值的点赋为 2, i % h = 0 & j % w = 0 i \% h =0 \& j\%w=0 i%h=0&j%w=0 的点赋为 − 2 × ( h × w − 1 ) + 1 -2\times (h\times w - 1) +1 −2×(h×w−1)+1
构造出来的矩阵就是 2 -4 2
然后我们惊奇的发现整体矩阵和变大了。
考虑为什么 就是会出现一些情况使得 n % h ≠ 0 n\%h \neq 0 n%h=0 或者 m % w ≠ 0 m\% w \neq 0 m%w=0 。
其实我们只需要保证每个子矩阵的举证和为 -1 ,这样相当于只有多出来的部分尽量大才更有可能满足总矩阵和大于 0 。所以把赋正值的点赋为 k k k, i % h = 0 & j % w = 0 i \% h =0 \& j\%w=0 i%h=0&j%w=0 的点赋为 − k × ( h × w − 1 ) + 1 -k\times (h\times w - 1) +1 −k×(h×w−1)+1 , k k k 更大就更能利用多余部分的矩阵。
#include<bits/stdc++.h>
using namespace std;
int n,m,h,w;
int a[505][505];
int main(){
cin>>n>>m>>h>>w;
int sum=0;
int k=501;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
if(i%h==0&&j%w==0) a[i][j]=-k*(h*w-1)-1;
else a[i][j]=k;
sum+=a[i][j];
}
if(sum>0){
printf("Yes\n");
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) printf("%d ",a[i][j]);
printf("\n");
}
}
else printf("No\n");
return 0;
}
/*
1 3 1 2
1 -2 1
*/