Processing math: 100%

Xmas Contest 2018

A - Art Time

問題

  • 与えられた画像で4色塗り分け問題を実践せよ

解法

ペイントで適当に。隣り合うセルに別々の3色が塗られていればそのセルは残りの1色とわかるが、途中でどうしても決められないところが出るので、仮定して進み、仮定した箇所をメモっておく。破綻した時にそこまで戻る、というのを繰り返すと手動全探索が出来る。Ctrl+Zは偉大。

B - Bit Smaller

問題

  • 34425=34425 のように、指数を下に下ろしても数が等しくなるような数字を、20181224以下で全列挙せよ

解法

全探索。せいぜい8桁なので、指数の項は多くとも 12345678 のよう3つまで。

入力はないので、多少時間かかっても答えをTextで提出すればよい。

さすがに指数部が3桁以上になることは無いだろうと考えて、その条件で証明の無い枝刈り。

後は、切る位置によって'0'が先頭に来る場合は成立しないことに注意。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# もうちょいスッキリ書きたい
from itertools import product
 
 
def test(n, s, c, spl):
    for sa, sb, tb in spl:
        str_a = s[sa:sb]
        str_b = s[sb:tb]
        if str_a[0] == '0' or str_b[0] == '0':
            return False
        c *= pow(int(str_a), int(str_b), 1000000009)
        if c > n:
            return False
    return n == c
 
 
def make_can(s, t):
    ms = max(s + 1, t - 2)
    return [[(s, i, t)] for i in range(ms, t)]
 
 
def make_cans():
    cans = {}
    for dab in range(2, 8):
        if dab == 2:
            can = make_can(0, 2)
        elif dab == 3:
            can = make_can(0, 3)
        elif dab == 4:
            can = make_can(0, 4)
            can.extend(a + b for a, b in product(make_can(0, 2), make_can(2, 4)))
        elif dab == 5:
            can = make_can(0, 5)
            can.extend(a + b for a, b in product(make_can(0, 2), make_can(2, 5)))
            can.extend(a + b for a, b in product(make_can(0, 3), make_can(3, 5)))
        elif dab == 6:
            can = make_can(0, 6)
            can.extend(a + b for a, b in product(make_can(0, 2), make_can(2, 6)))
            can.extend(a + b for a, b in product(make_can(0, 3), make_can(3, 6)))
            can.extend(a + b for a, b in product(make_can(0, 4), make_can(4, 6)))
            can.extend(a + b + c for a, b, c in product(make_can(0, 2), make_can(2, 4), make_can(4, 6)))
        elif dab == 7:
            can = make_can(0, 7)
            can.extend(a + b for a, b in product(make_can(0, 2), make_can(2, 7)))
            can.extend(a + b for a, b in product(make_can(0, 3), make_can(3, 7)))
            can.extend(a + b for a, b in product(make_can(0, 4), make_can(4, 7)))
            can.extend(a + b for a, b in product(make_can(0, 5), make_can(5, 7)))
            can.extend(a + b + c for a, b, c in product(make_can(0, 2), make_can(2, 4), make_can(4, 7)))
            can.extend(a + b + c for a, b, c in product(make_can(0, 2), make_can(2, 5), make_can(5, 7)))
            can.extend(a + b + c for a, b, c in product(make_can(0, 3), make_can(3, 5), make_can(5, 7)))
        else:
            raise NotImplementedError
        cans[dab] = can
    return cans
 
 
buf = []
cans = make_cans()
print(cans)
for n in range(1000000, 20181225):
    s = str(n)
    for digit_c in range(1, len(s) - 1):
        str_c = s[-digit_c:]
        if str_c[0] == '0':
            continue
        c = int(str_c)
        if n % c != 0:
            continue
        dab = len(s) - digit_c
        for ccc in cans[dab]:
            if test(n, s, c, ccc):
                buf.append(s)
                print(s, ccc)
                break
        else:
            continue
        break

  • 34×425=34425
  • 312×325=312325
  • 34×4250=344250
  • 492×205=492205
  • 312×3250=3213250
  • 34×42500=3442500
  • 34×72×875=3472875
  • 492×2050=4922050
  • 13×74×5725=13745725
  • 13×94×2125=13942125
  • 14×5692×45=14569245
  • 16×74×6975=16746975
  • 19×74×8225=19748225

綺麗。

ほとんどは指数部が 34=8174=2401 のように「2を素因数に多く持つ数+1」になり、整数部が5を素因数に多く持つことで、「1034の倍数+元の整数」となり成立している。

H - Hello, Xmas Contest 2018

問題

  • 任意の大きさの盤面のいくつかのマスに文字を書き込む
  • 書き込める文字は、'A'~'Z' と '*'
  • 各行の、最も左にある文字から、'*' を抜いて読むと、S になる
  • 各列の、最も上にある文字から、'*' を抜いて読むと、T になる
  • 書き込む必要のある最小マス数を求めよ

S = ABCF, T = EBDCA

    *EBDCA
    ↓↓↓↓↓↓
*→*E  D
A→          A
B→    B
C→        C   7マス書き込めば成立
F→          F

解法

ST に共通する文字は、必ず共有する位置に置くことができる。(複数回登場する文字は、同じ個数まで)

(H,W)=(S,T) な盤面を用意して、'A'が S で1文字目、T で5文字目に出てくるなら、(1,5) に'A'を書き込めばよい。

また、共通しない文字や、双方に登場する文字でも片方が多くて溢れるものは、「1文字目以外は」隠せる(もう一方から読まれない位置に置ける)。1文字目の後ろに置けばよい。

どちらかの1文字目がもう一方に出現しなかった場合は'*'で隠す必要があるが、これも1つさえあれば、盤面を1マス広げて (1,1) に置くことで縦横両方に隠すスペースを確保できる。

よって、c=A...ZcST をベースとし、S0Tに含まれなかったり、T0Sに含まれなかった場合のみ、+1すればよい。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from string import ascii_uppercase
 
from collections import Counter
 
s = input()
t = input()
cs = Counter(s)
ct = Counter(t)
ans = 0
for c in ascii_uppercase:
    tmp = 0
    if c in cs:
        tmp = cs[c]
    if c in ct:
        tmp = max(tmp, ct[c])
    ans += tmp
if s[0] not in t or t[0] not in s:
    ans += 1
print(ans)

programming_algorithm/contest_history/atcoder/2018/1224_xmascon18.txt · 最終更新: 2018/12/26 by ikatakos
CC Attribution 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0