目次

Xmas Contest 2018

Xmas Contest 2018

A - Art Time

A - Art Time

問題

解法

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

B - Bit Smaller

B - Bit Smaller

問題

解法

全探索。せいぜい8桁なので、指数の項は多くとも $1^23^45^{67}8$ のよう3つまで。

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

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

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

# もうちょいスッキリ書きたい
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

綺麗。

ほとんどは指数部が $3^4=81$ や $7^4=2401$ のように「2を素因数に多く持つ数+1」になり、整数部が5を素因数に多く持つことで、「$10^{3~4}$の倍数+元の整数」となり成立している。

H - Hello, Xmas Contest 2018

H - Hello, Xmas Contest 2018

問題

S = ABCF, T = EBDCA

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

解法

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

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

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

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

よって、$\displaystyle \sum_{c=A ... Z}{文字cの登場回数のSとTで多い方}$ をベースとし、$S_0$が$T$に含まれなかったり、$T_0$が$S$に含まれなかった場合のみ、$+1$すればよい。

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)