AtCoder Grand Contest 027D

AtCoder Grand Contest 027D - Modulo Matrix

题目大意

  • 要求构造一个 n ∗ n n*n nn的元素互异且值域为小于等于 1 0 15 10^{15} 1015正整数的矩阵,要求满足任意相邻两个数 x , y x,y x,y满足 m a x ( x , y ) m o d    m i n ( x , y ) = m max(x,y) mod min(x,y)=m max(x,y)modmin(x,y)=m,其中正整数 m m m为某个不确定的定值。
  • n ≤ 500 n≤500 n500

题解

  • 可以先把相邻的格子黑白染色,那么同种颜色之间没有干扰,
  • 一种最简单的构造是把所有黑格按正整数从小到大赋值,接着每个白格的值即为它相邻黑格的 l c m lcm lcm加上某个常数(比如是 1 1 1),但这样值域最坏大概为 ( n 2 ) 4 (n^2)^4 (n2)4级别,超过了限制。
  • 考虑怎样才能使值域减小,或者说考虑怎样才能使每个白格相邻的黑格的 l c m lcm lcm最小,
  • 用如下方式构造,使黑格所在的每条对角线对应一个质数,那每个黑格的值就是它所在的两条交叉对角线对应的质数之积,而白格和上面一样,
  • 这样可以使 l c m lcm lcm降到 n 4 n^4 n4级别,在值域的范围内。
  • 至于为什么要选择质数?
  • 很显然,若不选质数会存在有两数相等的情况。

代码

#include<cstdio>
#include<cstring>
using namespace std;
#define N 510
#define ll long long
int a[4 * N], p[100 * N];
ll sx[N][N], sy[N][N];
int main() {
	int n, i, j, s = 0;
	scanf("%d", &n);
	for(i = 2; i; i++) if(!p[i]) {
		a[++s] = i;
		if(s == 4 * n) break;
		for(j = 1; j * i < 100 * N; j++) p[i * j] = 1;
	}
	int t = 0;
	for(i = 0; i <= n + 1; i += 2) {
		t++;
		int x = i, y = 0;
		while(x <= n + 1 && y <= n + 1) sx[x][y] = a[t], x++, y++;
	}
	for(i = 2; i <= n + 1; i += 2) {
		t++;
		int x = 0, y = i;
		while(x <= n + 1 && y <= n + 1) sx[x][y] = a[t], x++, y++;
	}
	if(n % 2 == 0) i = n; else i = n + 1;
	for(i; i >= 0; i -= 2) {
		t++;
		int x = i, y = 0;
		while(x >= 0 && y <= n + 1) sy[x][y] = a[t], x--, y++;
	}
	if(n % 2 == 0) i = 1; else i = 2;
	for(i; i <= n + 1; i++) {
		t++;
		int x = n + 1, y = i;
		while(x >= 0 && y <= n + 1) sy[x][y] = a[t], x--, y++;
	}
	for(i = 1; i <= n; i++) {
		for(j = 1; j <= n; j++) {
			if(sx[i][j]) printf("%lld ", sx[i][j] * sy[i][j]);
			else printf("%lld ", sx[i][j - 1] * sx[i - 1][j] * sy[i - 1][j] * sy[i][j + 1] + 1);
		}
		printf("
");
	}
	return 0;
}
哈哈哈哈哈哈哈哈哈哈
原文地址:https://www.cnblogs.com/LZA119/p/13910019.html