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×w1)+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×w1)+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
*/
posted @ 2023-02-17 20:02  To_Heart  阅读(2)  评论(0编辑  收藏  举报  来源