1. 程式人生 > 其它 >[AGC030C] Coloring Torus

[AGC030C] Coloring Torus

\(\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;
}
夜畔流離回,暗歎永無殿。 獨隱萬花翠,空寂亦難遷。 千秋孰能為,明滅常久見。 但得心未碎,踏遍九重天。