zoukankan      html  css  js  c++  java
  • Coloring Torus(Atcoder Grand Contest 030 C)

    怎么外国都喜欢考脑筋急转弯……


    题意

    输入 $k$,要求构造一个 $n imes n$ 的矩阵($n$ 自选),使得恰好用 $k$ 中颜色把每个点都染色,并且同一种颜色的格子周围 相邻的每种颜色数量都相同。

    比如矩阵中有两个格子的颜色是 $4$,其中一个格子周围有三个(颜色)$3$ 和一个 $1$,那另一个格子周围也得有三个 $3$ 和一个 $1$,但周围颜色的顺序不必相同。

    矩阵的第 $1$ 行上面与第 $n$ 行相连,第 $1$ 列左面与第 $n$ 列相连。

    $kle 1000$,且自选的 $n$ 必须属于 $[1,500]$。

    题解

    先规定一下,颜色从 $1$ 到 $n$ 编号。

    首先 $kle 500$ 时很好做,令 $n=k$,第 $i$ 行全填 $i$ 就行了,所有格的行列相邻状况显然相同,不用说明了吧……

    如果 $kgt 500$,就得考虑奇怪的方法了。

    先思考一下,如果 $k$ 是 $4$ 的倍数,我们可以这么填:

    比如 $k=8$ 的情况,构造一个 $n=k/4 imes 2=4$ 的矩阵,长这样:

    $$1space 2space 3space 4$$

    $$5space 6space 7space 8$$

    $$1space 2space 3space 4$$

    $$5space 6space 7space 8$$

    这样粗暴且满足题意。

    但 $k$ 不是 $4$ 的倍数呢?

    我们考虑移位。

    要移位的话,说明我们还要借鉴前面的方法,至少所以矩阵的大小暂定为把 $k$ 上取整为 $4$ 的倍数,即 $⌊(k+3)/4⌋ imes 2$。

    但还不能简单地移位,比如 $k=6$ 时,每两行都填

    $$1space 2space 3space 4$$

    $$3space 4space 5space 6$$

    这样错位后,同一种颜色的格子的左右两格颜色都相同,但上下两格颜色就不一定相同了。

    所以我们考虑一种构造,使得同一种颜色的格子的上下左右四格的颜色 在某些意义上关于这种颜色固定。

    这就有一个很简单的方法了:规定第 $i$ 行第 $j$ 列的位置的颜色是 $(i+j+1)mod k$。这样直接满足上述性质。

    而且这样构造,还可以使两个颜色的相对位置固定。

    比如矩阵有一个位置的颜色是 $1$,它右边位置的颜色是 $2$,那么矩阵中每出现一个 $1$,它右边必有一个 $2$,反之同理,出现一个 $2$,它的左边就必有一个 $1$。

    我们称之为相对相邻性。该性质对于任何方向都成立。

    可以手玩一下 $k=3,4$ 的情况,发现两个矩阵分别是(其实矩阵不唯一)

    $$1space 2$$

    $$2space 3$$

    $$1space 2$$

    $$4space 3$$

    两个矩阵的长宽 $n$ 根据之前说过的式子,可算出都是 $2$。然后发现第二个矩阵的那个 $4$ 模 $n$ 后等于第一个矩阵对应的那个 $2$ ?

    我们考虑这是怎么转化过去的。

    当 $k=3$ 时,矩阵显然。

    把 $k$ 加 $1$,即多了一种要用的颜色,我们把偶数行的 $2$ 换成了 $4$,保留了奇数行的 $2$。

    好像就是把奇偶行分类,新加一种颜色时,把偶数行的对应颜色值 $+n$?

    但是这个很好证明么?……依然用这个方法,换个大点的矩阵

    $k=5,6$ 的情况

    $$3space 4space 1space 2$$

    $$4space 5space 2space 3$$

    $$1space 2space 3space 4$$

    $$2space 3space 4space 5$$

    $$3space 4space 1space 2$$

    $$4space 5space 6space 3$$

    $$1space 2space 3space 4$$

    $$6space 3space 4space 5$$

    两个矩阵的 $n$ 都是 $4$。

    其实就是把偶数行的 $2$ 都通过 $+n$,换成了新的颜色 $6$。

    然后我们惊奇地发现这个矩阵满足题意。

    用上新的颜色的证明就不说了。

    那怎么证明每种颜色周围的每种颜色数量都相同?

    首先,新搞出来的这种颜色肯定都满足要求,因为在它们之前的颜色就满足要求。

    然后,我们考虑它们周围的格子的颜色。

    根据我们的构造方式,可以证明,对于任意一个颜色为 $x$ 的格子相邻的某个方向相邻的数,它一定恰好只在所有颜色为 $x$ 的格子的这个方向的相邻位置出现。

    这个结论可以根据之前的一段加粗的性质得出。

    如果是这样的话,那么周围的格子的颜色对应的所有格子 就必定都作了同样的修改,所以同一种颜色的相邻情况一定还相同。

    但是多次修改矩阵后,这个性质还满足吗?

    仍然满足,因为修改一次矩阵后任意两种颜色都满足相对相邻性的话,修改两次或更多次矩阵后也满足,就如同第一次修改一样,该性质可传递

    所以 $k$ 不是 $4$ 的倍数时的做法确定了:

    确定 $n$(前面说过了)

    对于奇数行,$col_{i,j}space =(space (r+c)mod n) +1$

    对于偶数行,$col_{i,j}space =(space (r+c)mod n) +n+1$

    如果 $col_{i,j}$ 大于 $k$ 就减去 $n$。

    其实就是稍微转化一下做法,对于偶数行,编号超过 $n$ 的颜色能放就尽量放。做法的重点是维护构造的相对相邻性

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int main()
     4 {
     5     int k;
     6     while (scanf("%d", &k) != EOF)
     7     {
     8         if (k <= 500)
     9         {
    10             printf("%d
    ", k);
    11             for (int i = 1; i <= k; ++i) for (int j = 1; j <= k; ++j)
    12                 printf("%d%c", i, " 
    "[j == k]);
    13         }
    14         else
    15         {
    16             int n = (k + 3) / 4 * 2;
    17             printf("%d
    ", n);
    18             for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j)
    19             {
    20                 int x;
    21                 if (i & 1) x = (i + j) % n;
    22                 else x = n + (i + j) % n;  
    23                 if (x >= k) x -= n;     
    24                 printf("%d%c", x + 1, " 
    "[j == n]);
    25             }
    26         }
    27     }
    28     return 0;
    29 }
    View Code
  • 相关阅读:
    从苏宁电器到卡巴斯基第13篇:我在苏宁电器当营业员 V
    从苏宁电器到卡巴斯基第12篇:我在苏宁电器当营业员 IV
    从苏宁电器到卡巴斯基第11篇:我在苏宁电器当营业员 III
    从苏宁电器到卡巴斯基第10篇:我在苏宁电器当营业员 II
    从苏宁电器到卡巴斯基第09篇:我在苏宁电器当营业员 I
    从苏宁电器到卡巴斯基第08篇:来到苏宁之前的过渡
    【目录】从苏宁电器到卡巴斯基
    从苏宁电器到卡巴斯基第07篇:我在佳木斯的日子(下)
    从苏宁电器到卡巴斯基第06篇:我在佳木斯的日子(中)
    从苏宁电器到卡巴斯基第05篇:我在佳木斯的日子(上)
  • 原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/atc030c.html
Copyright © 2011-2022 走看看