#構造,黑白染色#AT4378 [AGC027D] Modulo Matrix
阿新 • • 發佈:2022-03-20
題目
構造一個 \(n*n(n\leq 500)\) 的矩陣,滿足元素均為正整數,不超過 \(10^15\) 且互不相同,
並且相鄰兩數若較大的為 \(x\),較小的為 \(y\),那麼任意相鄰兩數 \(x\bmod y\) 都相同。
分析
其實相鄰在構造題中有一個很好的辦法就是黑白染色,並且讓 \(x\bmod y=1\) 能使 \(x\) 儘量小。
綜合考慮值域和互不相同,可以發現讓白格為四個黑格的最小公倍數加一,那麼黑格互不相同就可以讓白格也儘量不同。
有一個很妙的方法就是黑格所在的對角線標記一個質數,這樣每個黑格被正對角線和反對角線的兩個質數相乘,
那麼由於至少有一條對角線不同,那麼黑格一定互不相同,白格也對應的互不相同,當然 \(n=2\)
然後前 \(2n\) 個質數不超過 \(16n\),所以四個數的最小公倍數理論上最大為 \(4*10^{15}\) 實際上肯定達不到這個上界
程式碼
#include <iostream> using namespace std; const int M=8011,N=511,dx[4]={0,0,1,-1},dy[4]={1,-1,0,0}; int v[M+1],p[M+1],n,m; typedef long long lll; lll a[N][N]; lll gcd(lll x,lll y){return y?gcd(y,x%y):x;} int main(){ ios::sync_with_stdio(0); cin>>n,v[1]=1; if (n==2){ cout<<"2 3\n5 16\n"; return 0; } for (int i=2;i<=M;++i) if (!v[i]){ p[++m]=i; for (int j=i;j<=M;j+=i) v[j]=1; } for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) if ((i+j+1)&1) a[i][j]=p[(i+j)>>1]*p[n+(i-j+n+1)/2]; for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) if ((i+j)&1){ a[i][j]=1; for (int k=0;k<4;++k){ int x=i+dx[k],y=j+dy[k]; if (x<1||y<1||x>n||y>n) continue; a[i][j]=a[i][j]/gcd(a[i][j],a[x][y])*a[x][y]; } ++a[i][j]; } for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) cout<<a[i][j]<<(char)(j==n?10:32); return 0; }