[构造] [AGC027D] Modulo Matrix

posted on 2024-07-18 23:37:14 | under | source

将棋盘黑白染色,一条“关系”不会同时涉及相同颜色,所以我们构造其中一种颜色即可(如黑色)。

为了去掉 \(\max,\min\),令白色格子 \(P\) 永远大于周围黑色格子 \(a,b,c,d\)。那么题目的限制可以转化为:\(P=k\times \rm {lcm}(a,b,c,d)+m\)\(m\) 是模数。

可以想到奇偶性,只要让黑色格子是奇数,然后 \(m\)\(1\) 以改变奇偶性,这样的话白色格子一定是偶数,不会和黑色重合。

又因为黑色格子总是可以用两条对角线表示的,所以有以下构造:

  1. 将每条对角线赋值为不同奇质数。
  2. 每个黑色格子,取值为两条对角线乘积。显然黑色格子质因子不同,故不会重复。
  3. 每个白色格子,取值为四条相邻对角线乘积(即相邻黑色格子 \(\rm lcm\))加一。显然质因子不同,加一后依旧不同。

注意一下,这样构造的上界会超出限制,只需要更改一下,让对角线质数交替出现即可。

代码

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int N = 5e2 + 5, M = 1e4 + 5, P = 1e15;
int n, f1[M], f2[M], n1, n2, a[N][N], mx;

inline bool check(int x){
	for(int i = 2; i * i <= x; ++i) 
		if(x % i == 0) return false; 
	return true;
}
inline void sb(int f[], int n){
	sort(f + 1, f + 1 + n);
	int b[M], pos = 0;
	for(int i = 1; i <= n; i += 2) b[i] = f[++pos];
	for(int i = n - 1; i > 1; i -= 2) b[i] = f[++pos];
	for(int i = 1; i <= n; ++i) f[i] = b[i];
}
inline int F1(int x, int y) {return max(1ll, f1[(n - (x - y) + 1) / 2]);}
inline int F2(int x, int y) {return max(1ll, f2[(x + y) / 2]);}
signed main(){
	srand(time(0));
	cin >> n;
	if(n == 2){
		puts("4 7");
		puts("23 10");
		return 0;
	}
	int len = (n + 1) / 2;
	for(int cnt = 0, i = 3; ; ++i)
		if(check(i)){
			++cnt;
			if(cnt > 4 * len - 2) break;
			if(cnt <= 2 * len - 1) f1[++n1] = i;
			else f2[++n2] = i;
		} 
	sb(f1, n1), sb(f2, n2);
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j){
			if(!((i + j) & 1)) a[i][j] = F1(i, j) * F2(i, j);
		}
	for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= n; ++j)
			if((i + j) & 1) a[i][j] = F1(i - 1, j) * F1(i + 1, j) * F2(i, j - 1) * F2(i, j + 1) + 1;
	for(int i = 1; i <= n; ++i){
		for(int j = 1; j <= n; ++j) printf("%lld ", a[i][j]);
		printf("\n");
	}
	return 0;
}
posted @ 2026-01-12 20:13  Zwi  阅读(2)  评论(0)    收藏  举报