Grid Coloring

链接:https://ac.nowcoder.com/acm/contest/5671/G
来源:牛客网

Roundgod draws a grid graph of size nn with n × n n \times n n×n cells. She can use one of k k k colors to color every edge once, but lzr gives her some limits.

  1. lzr loves balance. All colors should appear in the same number of
    times.
  2. lzr loves complexity. The graph should not contain any monochromatic
    cycle.
  3. lzr hates monotone. Each whole horizontal or vertical line of the
    graph should contain at least two colors.
    在这里插入图片描述

Roundgod is so divine that she doesn’t want to waste her god’s power to solve this problem. Could you give her a solution?
输入描述:
The input contains multiple test cases. The first line of input contains one integer T   ( 1 ≤ T ≤ 100 ) T\ (1\le T\le100) T (1T100).
In the following T T T lines, each line contains two integers n , k   ( 1 ≤ n ≤ 200 , 1 ≤ k ≤ 2 ( n + 1 ) n ) n,k\ (1\le n\le200,1\le k\le2(n+1)n) n,k (1n200,1k2(n+1)n) describing one test case.
输出描述:
For each test case, if there’s no solution, please output “-1”.
Otherwise, output 2 ( n + 1 ) 2(n+1) 2(n+1) lines.
For the first n + 1 n+1 n+1 lines, each line contains nn integers, denoting colors of edges on every horizontal line.
For the last n + 1 n+1 n+1 lines, each line contain nn integers, denoting colors of edges on every vertical line.
示例1

输入
2
2 3
2 5
输出
1 2
3 1
3 2
1 3
2 1
2 3
-1

首先,对于 n = 1 n=1 n=1 k = 1 k=1 k=1 ( 2 ⋅ ( n + 1 ) ⋅ n ) m o d    k ≠ 0 (2 · (n + 1) · n)\mod k\not=0 (2(n+1)n)modk=0的情况直接输出 − 1 -1 1
对于其他情况,首先把要填的数字相同的写在一起组成序列 s e q seq seq。如 n = 3 n=3 n=3 k = 4 k=4 k=4的情况 s e q = 1 , 1 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 4 , 4 seq=1 ,1 ,1 ,1 ,1 ,1 ,2 ,2 ,2 ,2 ,2 ,2 ,3 ,3 ,3 ,3 ,3 ,3 ,4 ,4 ,4 ,4 ,4 ,4 seq=1,1,1,1,1,1,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4
然后按下图所示顺序依次填入各边。
在这里插入图片描述
如果按照这种策略填写,首先一定满足不存在环使得环的边颜色相同。
证明:首先 k ≥ 2 k≥2 k2,而按照这种策略红色的边和黑色的边数量相等,因此红色的边与黑色的边的颜色一定不同,而对于图中任意一个环一定同时包含红色的边和黑色的边,因此一定不存在环使得环的边颜色相同。
其次是对于任意一个行和列的边颜色不能相同。由于行和列对称,因此这里就各列进行讨论。
经验证发现只有样例的第一个数据不满足,其余情况都满足。
这里就大概证明一下,可能不是很严谨。
若某一列颜色都相同,设该列的边中编号最小的为 i m i n i_{min} imin,最大的为 i m a x i_{max} imax,则应当满足 m i n ( i m i n , 2 ⋅ ( n + 1 ) ⋅ n − i m a x ) ≥ 2 ⋅ ( n + 1 ) ⋅ n 3 min(i_{min},2·(n+1)·n-i_{max})≥\frac{2·(n+1)·n}{3} min(imin,2(n+1)nimax)32(n+1)n
对于 n = 2 n=2 n=2 k = 3 k=3 k=3,中间一列刚好满足等号条件。
而随着 n n n的增长,取得 i m i n i_{min} imin的边会逐渐由上一条红边跳到下一条包含边数更多的边上,而由于图中红线包含的边数增长部分为线性增长,因此这一变化可以近似看做是线性增长;同理, 2 ⋅ ( n + 1 ) ⋅ n − i m a x 2·(n+1)·n-i_{max} 2(n+1)nimax也可以看做是线性增长的,而等式右边 2 ⋅ ( n + 1 ) ⋅ n 3 ∝ n 2 \frac{2·(n+1)·n}{3}∝n^2 32(n+1)nn2,因此除样例外都满足条件。

#include<bits/stdc++.h>

#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define ull unsigned long long
#define vi vector<int>
#define pii pair<int,int>
#define mii unordered_map<int,int>
#define msi unordered_map<string,int>
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 405, M = 1e5 + 10;
int T, n, m, k;
int seq[M];
int a[N][N];

inline void change(int x, int y, int z, int v) {
    switch (z) {
        case 1:
            a[2 * x - 1][y] = v;
            break;
        case 2:
            a[2 * x + 1][y] = v;
            break;
        case 3:
            a[2 * x][y] = v;
            break;
        default:
            a[2 * x][y + 1] = v;
    }
}

inline int ask(int x, int y, int z) {
    switch (z) {
        case 1:
            return a[2 * x - 1][y];
        case 2:
            return a[2 * x + 1][y];
        case 3:
            return a[2 * x][y];
        default:
            return a[2 * x][y + 1];
    }
}

inline void solve() {
    int tot = 0, i = 2;
    for (; i - 1 <= n; i += 2)
        repi(j, 1, i - 1) {
            change(j, i - j, 1, seq[++tot]);
            change(j, i - j, 3, seq[++tot]);
        }
    i--;
    for (; i <= 2 * n; i += 2)
        repi(j, i - n, n) {
            change(j, i - j, 4, seq[++tot]);
            change(j, i - j, 2, seq[++tot]);
        }
    i = 3;
    for (; i - 1 <= n; i += 2)
        repi(j, 1, i - 1) {
            change(j, i - j, 1, seq[++tot]);
            change(j, i - j, 3, seq[++tot]);
        }
    i--;
    for (; i <= 2 * n; i += 2)
        repi(j, i - n, n) {
            change(j, i - j, 4, seq[++tot]);
            change(j, i - j, 2, seq[++tot]);
        }
}

int main() {
    T = qr();
    while (T--) {
        n = qr(), k = qr();
        if (n == 2 && k == 3) {
            puts("1 2\n3 1\n3 2\n1 3\n2 1\n2 3");
            continue;
        }
        if ((2 * (n + 1) * n) % k || n == 1 || k == 1) {
            puts("-1");
            continue;
        }
        m = (2 * (n + 1) * n) / k;
        repi(i, 1, k)repi(j, 1, m)seq[(i - 1) * m + j] = i;
        solve();
        repi(i, 1, n)repi(j, 1, n)printf("%d%c", ask(i, j, 1), ce(j, n));
        repi(i, 1, n)printf("%d%c", ask(n, i, 2), ce(i, n));
        repi(i, 1, n)repi(j, 1, n)printf("%d%c", ask(j, i, 3), ce(j, n));
        repi(i, 1, n)printf("%d%c", ask(i, n, 4), ce(i, n));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_sky123_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值