2020牛客暑期多校训练营Grid Coloring(构造)

Grid Coloring

题目描述

2020牛客暑期多校训练营Grid Coloring(构造)_第1张图片

输入描述:

2020牛客暑期多校训练营Grid Coloring(构造)_第2张图片

输出描述:

2020牛客暑期多校训练营Grid Coloring(构造)_第3张图片

示例1

输入

2
2 3
2 5

输出

1 2
3 1
3 2
1 3
2 1
2 3
-1

题目大意

给出一个 n ∗ n n*n nn的正方形网格,有 k k k种颜色。现要求你将网格的每一条边染色,使得满足以下3个条件。
l i m i t 1 limit1\qquad limit1所有的颜色的边的数量都是相等的
l i m i t 2 limit2\qquad limit2没有一个环是只有一种颜色的。
l i m i t 3 limit3\qquad limit3没有一条竖直或水平的线是只有一种颜色的。

分析

无解

首先当 n = 1 n=1 n=1时,竖直和水平线总是只有1种颜色的,违反 l i m i t 3 limit3 limit3。当 k = 1 k=1 k=1时,只能染一种颜色,违反 l i m i t 2 , 3 limit2,3 limit2,3。当 总边数   m o d   k ≠ 0 \,mod\,k\not=0 modk=0时显然无法满足 l i m i t 1 limit1 limit1,因此也是无解的。

构造

这里先给出构造方法,再证明。
2020牛客暑期多校训练营Grid Coloring(构造)_第4张图片
如图,按照图中 1 , 2 , … 1,2,\dots 1,2,的顺序进行染色,依次染 1 , 2 , 3 , … , k , 1 , 2 , 3 , … 1,2,3,\dots,k,1,2,3,\dots 1,2,3,,k,1,2,3,

证明:
对于 l i m i t 1 limit1 limit1,显然顺序染色一定保证每个颜色相同次数。
对于 l i m i t 2 limit2 limit2,如果环是 1 ∗ 1 1*1 11的,那么纵向的边是编号相邻的,颜色必不同。
         \qquad\qquad\,\,\,\,\,\,\,\, 如果环是 A ∗ B A*B AB的,那么大于1的那条边有相邻的横边或者有相邻的两条纵边,颜色也不会相同。(纵边只要用n,i,j表示出来modk就可以看出来了,后文会加以证明)
对于 l i m i t 3 limit3 limit3,从上一条可以得出,横的边一定是不同色的,满足,接下来证明纵边。

经过推导发现,纵边用 n n n表示后,相邻的两边的差是 ( 2 n − 1 ) (2n-1) (2n1),因此,我们只要证明 g c d ( 2 n − 1 , k ) = 1 gcd(2n-1,k)=1 gcd(2n1,k)=1就可以了。由于总边数是 2 n ( n + 1 ) 2n(n+1) 2n(n+1),所以 k ∣ 2 n ( n + 1 ) k|2n(n+1) k2n(n+1)。因此可以证明 gcd ⁡ ( 2 n − 1 , 2 n ( n + 1 ) ) = 1 \gcd(2n-1,2n(n+1))=1 gcd(2n1,2n(n+1))=1

       gcd ⁡ ( 2 n ( n + 1 ) , 2 n + 1 ) \,\,\,\,\,\,\gcd(2n(n+1),2n+1) gcd(2n(n+1),2n+1)
= gcd ⁡ ( 2 n + 1 , 2 n ( n + 1 ) − n ( 2 n + 1 ) ) =\gcd(2n+1,2n(n+1)-n(2n+1)) =gcd(2n+1,2n(n+1)n(2n+1))
= gcd ⁡ ( 2 n + 1 , n ) =\gcd(2n+1,n) =gcd(2n+1,n)
= gcd ⁡ ( n , 2 n + 1 − n ) =\gcd(n,2n+1-n) =gcd(n,2n+1n)
= gcd ⁡ ( n , n + 1 ) =\gcd(n,n+1) =gcd(n,n+1)
(用辗转相除法得)
因此相邻的纵向的边是不同色的。
所以上述策略是可行的。

代码

#include
#define ll long long
using namespace std;
const int MAXN=210;
int a[MAXN][MAXN],b[MAXN][MAXN];
int main()
{
	int t,n,k;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&k);
		if(n==1||k==1||2*n*(n+1)%k){puts("-1");continue;}
		int cnt=0;//第cnt条边的色是(cnt-1)%k+1
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				cnt=cnt%k+1;
				a[i][j]=cnt;
			}
			for(int j=1;j<=n+1;j++){
				cnt=cnt%k+1;
				b[j][i]=cnt;
			}
		}
		for(int i=1;i<=n;i++){
			cnt=cnt%k+1;
			a[n+1][i]=cnt;
		}
		for(int i=1;i<=n+1;i++){
			for(int j=1;j<=n;j++){
				printf("%d ",a[i][j]);
			}puts("");
		}
		for(int i=1;i<=n+1;i++){
			for(int j=1;j<=n;j++){
				printf("%d ",b[i][j]);
			}puts("");
		}
	}
}

END

难的构造题,灰常难的构造题。

你可能感兴趣的:(2020牛客多校,构造)