Grid Coloring
题目描述:
R o u n d g o d Roundgod Roundgod绘制了一个包含 n ∗ n n*n n∗n格子的图,他可以用 k k k种颜色,对每一条边进行染色,但有一些限制:
- 每种颜色必须出现相同次数
- 图上不能有单色环
- 每一行和每一列,至少包含 2 2 2种颜色。
输入描述:
输入包含多个测试用例。 输入的第一行包含一个整数 T T T ( ( ( 1 1 1 ≤ \le ≤ T T T ≤ \le ≤ 100 100 100 ) ) )在接下来的 T T T行中,每行包含两个整数 n n n, k k k ( ( ( 1 1 1 ≤ \le ≤ n n n ≤ \le ≤ 200 200 200, 1 1 1 ≤ \le ≤ k k k ≤ \le ≤ 2 ( n + 1 ) n ) 2(n+1)n) 2(n+1)n),描述一个测试用例。
输出描述:
对于每个测试用例,如果没有解决方案,请输出 − 1 -1 −1。否则,输出 2 ( n + 1 ) 2(n+1) 2(n+1)行。 对于前 n + 1 n+1 n+1行,每行包含 n n n个整数,表示每条水平线上的边缘颜色;对于后 n + 1 n+1 n+1行,每行包含 n n n个整数,表示每条垂直线上的边缘颜色。
样例输入:
2
2 3
2 5
样例输出:
1 2
3 1
3 2
1 3
2 1
2 3
-1
思路:
首先,我们可以排除三种无解的情况:
k
=
1
,
n
=
1
,
2
n
(
n
+
1
)
k=1,n=1,2n(n+1)
k=1,n=1,2n(n+1)
m
o
d
mod
mod
k
!
=
0
k!=0
k!=0
然后我们就按照如下方式对图进行标号:
所以我们的标号方式是:自顶向下分别给边按照
1
1
1到
n
n
n的顺序标号(如上图),然后我们将颜色
1
1
1到
k
k
k按照顺序轮流放到这些边上。
1.对于每一个
1
∗
1
1*1
1∗1的小环,两条纵边必定是相邻的序号,所以染的颜色必然不同
2.对于任意一个
a
(
a
+
b
)
,
b
>
0
a(a+b),b>0
a(a+b),b>0的环,横向边必定有相邻序号,所以染的颜色必然不同,由此又可以证明所有的横向边都是异色的
3.对于任意一个
(
a
+
b
)
a
,
b
>
0
(a+b)a,b>0
(a+b)a,b>0的环,如果他的横向边长为1,那么他就有相邻的纵向边,如果他的横向边
>
1
>1
>1那么他就有相邻横向边
所以任意一个环和横边均异色。
然后观察上图,发现:任意两条相邻纵向边的序号差必定为
2
n
+
1
2n+1
2n+1
推理到这一步,我们只要证明任意两条相邻纵向边必定异色即可,即
g
c
d
(
k
,
2
n
+
1
)
=
1
gcd(k,2n+1)=1
gcd(k,2n+1)=1,也就是
g
c
d
(
2
n
(
n
+
1
)
,
2
n
+
1
)
=
1
gcd(2n(n+1),2n+1)=1
gcd(2n(n+1),2n+1)=1
证明:
g
c
d
(
2
n
(
n
+
1
)
,
2
n
+
1
)
=
1
gcd(2n(n+1),2n+1)=1
gcd(2n(n+1),2n+1)=1
↔
\leftrightarrow
↔
g
c
d
(
2
n
(
n
+
1
)
−
n
(
2
n
+
1
)
,
2
n
+
1
)
=
1
gcd(2n(n+1)-n(2n+1),2n+1)=1
gcd(2n(n+1)−n(2n+1),2n+1)=1
↔
\leftrightarrow
↔
g
c
d
(
n
,
2
n
+
1
−
n
)
=
1
gcd(n,2n+1-n)=1
gcd(n,2n+1−n)=1
↔
\leftrightarrow
↔
g
c
d
(
n
,
n
+
1
)
=
1
gcd(n,n+1)=1
gcd(n,n+1)=1
得证。
我还真不信如此复杂的推理得出的代码竟是如此简便…
A C AC AC C o d e Code Code:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=205;
int a[MAXN][MAXN],b[MAXN][MAXN],T,n,k,t;
int main(){
scanf("%d",&T);
while(T--){
t=0;
scanf("%d%d",&n,&k);
if(n==1|| k==1||(2*n*(n+1))%k){
puts("-1");
continue;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
t=t%k+1;
a[i][j]=t;
}
for(int j=0;j<=n;j++){
t=t%k+1;
b[j][i]=t;
}
}
for(int i=0;i<n;i++){
t=t%k+1;
a[n][i]=t;
}
for(int i=0;i<=n;i++){
for(int j=0;j<n;j++)
printf("%d ",a[i][j]);
puts("");
}
for(int i=0;i<=n;i++){
for(int j=0;j<n;j++)
printf("%d ",b[i][j]);
puts("");
}
}
}