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=81 や 74=2401 のように「2を素因数に多く持つ数+1」になり、整数部が5を素因数に多く持つことで、「103~4の倍数+元の整数」となり成立している。
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
解法
S と T に共通する文字は、必ず共有する位置に置くことができる。(複数回登場する文字は、同じ個数まで)
(H,W)=(Sの文字数,Tの文字数) な盤面を用意して、'A'が S で1文字目、T で5文字目に出てくるなら、(1,5) に'A'を書き込めばよい。
また、共通しない文字や、双方に登場する文字でも片方が多くて溢れるものは、「1文字目以外は」隠せる(もう一方から読まれない位置に置ける)。1文字目の後ろに置けばよい。
どちらかの1文字目がもう一方に出現しなかった場合は'*'で隠す必要があるが、これも1つさえあれば、盤面を1マス広げて (1,1) に置くことで縦横両方に隠すスペースを確保できる。
よって、∑c=A...Z文字cの登場回数のSとTで多い方 をベースとし、S0がTに含まれなかったり、T0がSに含まれなかった場合のみ、+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) |