\(\text{Problem}:\)Coloring Torus
\(\text{Solution}:\)
首先考虑当 \(K\leq 500\) 时如何构造。一种显然的构造方式是第 \(i\) 行全为 \(i\)。但经尝试,这种构造方式难以推广到 \(K>n\)。
注意该矩阵满足的性质。不难发现,当 \(a_{i,j}=a_{i+1,j+1}\) 时,只需满足集合 \(\{a_{i-1,j},a_{i,j-1}\}\) 与 \(\{a_{i+2,j+1},a_{i+1,j+2}\}\) 相等。而 \(a_{i,j},a_{i+1,j+1}\) 位于同一条对角线上。如果令 \(a_{i-1,j}=a_{i+1,j+2}\) 且 \(a_{i,j-1}=a_{i+2,j+1}\),我们可以猜想:是否存在一种构造方式,使得每一条对角线上的 \(a\) 的都相等呢?
答案是肯定的。若对角线可以无限延长,那么只需对每一条对角线赋不同的值即可。但是在矩阵的 \(2n-1\) 条有限长的对角线上,可以发现,对前 \(n\) 条对角线(此处对角线按照从左上往右下的顺序标号,下同)赋 \(n\) 种不同的值,而第 \(i+n\) 条对角线上的权值应与第 \(i\) 条对角线上的权值相同。这样就解决了 \(K\leq n\) 的问题。
当 \(K>n\) 时,考虑重新回归到一开始找出的矩阵性质。当 \(a_{i-1,j}\) 与 \(a_{i+1,j+2}\) 被同时替换为 \(x\) 时,仍然满足题意。这提示我们可以在对角线上将行标号为奇数的位置同时改变为另一个数。而权值不同的对角线有 \(n\) 条,故当 \(K\leq 2n\) 时都可以构造。注意当 \(n\) 为奇数时是无法按照以上方法构造的(原因显然),但 \(n_{max}=500\) 为偶数,故无需考虑。
\(\text{Code}:\)
#include <bits/stdc++.h>
//#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=1010;
inline int read()
{
int s=0, w=1; ri char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
return s*w;
}
int K,n,a[N][N];
signed main()
{
K=read();
n=min(K,500);
printf("%d\n",n);
for(ri int i=1;i<=n;i++)
{
for(ri int j=1;j<=n;j++)
{
a[i][j]=(i+j-2)%n+1;
}
}
K-=n;
for(ri int T=1;T<=K;T++)
{
int cnt=0;
for(ri int i=1;i<=T;i++)
{
cnt++;
if(cnt&1) a[i][T-i+1]=T+n;
}
for(ri int i=1;i<=n-T;i++)
{
cnt++;
if(cnt&1) a[i+T][n-i+1]=T+n;
}
}
for(ri int i=1;i<=n;i++,puts(""))
for(ri int j=1;j<=n;j++)
printf("%d ",a[i][j]);
return 0;
}