[构造] [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\) 以改变奇偶性,这样的话白色格子一定是偶数,不会和黑色重合。
又因为黑色格子总是可以用两条对角线表示的,所以有以下构造:
- 将每条对角线赋值为不同奇质数。
- 每个黑色格子,取值为两条对角线乘积。显然黑色格子质因子不同,故不会重复。
- 每个白色格子,取值为四条相邻对角线乘积(即相邻黑色格子 \(\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;
}

浙公网安备 33010602011771号