agc027D – Modulo Matrix(構造 黑白染色)

自為風月馬前卒發表於2018-09-28

題意

題目連結

構造一個(n * n)的矩陣,要求任意相鄰的兩個數(a,b),使得(max(a,b) \% min(a,b)
ot = 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
23 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;
}

相關文章