題意
構造一個\(n * n\)的矩陣,要求任意相鄰的兩個數\(a,b\),使得\(max(a,b) \% min(a,b) \not = 0\)
Sol
我的思路:
假設\(mod = 1\),那么可以在第一行放2 3 4 5 \(\dots\),第一列同理也這樣放
對於任意位置\(i\),一定滿足要求的一個數是a[i - 1][j] * a[i][j - 1] / __gcd(a[i - 1][j], a[i][j - 1]) + 1
然而最后的數大到上天啊。。。
標算挺巧妙的,首先把整個圖黑白染色,那么同色點之間是互不影響的。
考慮構造\(mod = 1\)的矩陣。
若白點的權值確定了,那么黑點的權值應當是所有相鄰白點的\(lcm\)+1,
那所有白點的權值怎么確定呢?
考慮直接用素數填充對於正對角線和負對角線上的每個點分配一個不同的素數
那么任意白點的權值為所在正對角線上的素數 乘 負對角線的素數
這樣算出來最大的$a_{ij} = 414556486388264 $,滿足要求
不過為啥數組要開1000才能過???
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 1e5 + 10;
int N;
int a[1001][1001], vis[MAXN], prime[MAXN], tot;
void GetPhi() {
vis[1] = 1;
for(int i = 2; i; i++) {
if(!vis[i]) prime[++tot] = i;
if(tot == 1000) break;
for(int j = 1; j <= tot && (i * prime[j] <= 10000); j++) {
vis[i * prime[j]] = 1;
if(!(i % prime[j])) break;
}
}
}
int lcm(int x, int y) {
if(x == 0 || y == 0) return x + y;
return x / __gcd(x, y) * y;
}
main() {
GetPhi();
cin >> N;
if(N == 2) {
printf("4 7\n23 10");
return 0;
}
for(int i = 1; i <= N; i++)
for(int j = 1; j <= N; j++)
if(!((i + j) & 1)) a[i][j] = prime[(i + j) / 2] * prime[N + (i - j) / 2 + (N + 1) / 2];
for(int i = 1; i <= N; i++)
for(int j = 1; j <= N; j++)
if(!a[i][j])
a[i][j] = lcm(lcm(a[i - 1][j], a[i][j - 1]), lcm(a[i][j + 1], a[i + 1][j])) + 1;
for(int i = 1; i <= N; i++, puts(""))
for(int j = 1; j <= N; j++)
cout << a[i][j] << " ";
return 0;
}
