import itertools
import sys
sys.setrecursionlimit(100000)
answers = {}
def memoize(func):
def f(*args):
if args not in answers:
answers[args] = func(*args)
return answers[args]
return f
def split_along(s, points):
points = [0] + points + [len(s)]
for a,b in zip(points, points[1:]):
yield s[a:b]
def special_partition(s):
split_points = []
for i in range(len(s)):
if any(s[i:].startswith(prefix) for prefix in ("211131", "211132", "23113", "21321" "2322")):
split_points.append(i+1)
return list(split_along(s, split_points))
f = lambda s: "".join(str(len(list(v)))+k for k,v in itertools.groupby(s))
def g(s,x):
for i in range(x):
s = f(s)
return s
def show_sequence(s, max):
for x in range(max):
print g(s,x)
min_visited_depth = float("inf")
@memoize
def size(s, n, m=None):
global min_visited_depth
if n < min_visited_depth:
#print n,
min_visited_depth = n
if len(s) > 100:
raise Exception("failed to cleave efficiently on {}".format(s))
if n == 0:
return len(s)
pieces = special_partition(s)
piece_sizes = [size(f(piece), n-1, m) for piece in pieces]
result = sum(piece_sizes)
if m: result = result % m
return result
try:
print size("3", 500, 100)
except Exception as e:
print e.message
aW1wb3J0IGl0ZXJ0b29scwoKaW1wb3J0IHN5cwpzeXMuc2V0cmVjdXJzaW9ubGltaXQoMTAwMDAwKQoKCmFuc3dlcnMgPSB7fQpkZWYgbWVtb2l6ZShmdW5jKToKICAgIGRlZiBmKCphcmdzKToKICAgICAgICBpZiBhcmdzIG5vdCBpbiBhbnN3ZXJzOgogICAgICAgICAgICBhbnN3ZXJzW2FyZ3NdID0gZnVuYygqYXJncykKICAgICAgICByZXR1cm4gYW5zd2Vyc1thcmdzXQogICAgcmV0dXJuIGYKCmRlZiBzcGxpdF9hbG9uZyhzLCBwb2ludHMpOgogICAgcG9pbnRzID0gWzBdICsgcG9pbnRzICsgW2xlbihzKV0KICAgIGZvciBhLGIgaW4gemlwKHBvaW50cywgcG9pbnRzWzE6XSk6CiAgICAgICAgeWllbGQgc1thOmJdCgpkZWYgc3BlY2lhbF9wYXJ0aXRpb24ocyk6CiAgICBzcGxpdF9wb2ludHMgPSBbXQogICAgZm9yIGkgaW4gcmFuZ2UobGVuKHMpKToKICAgICAgICBpZiBhbnkoc1tpOl0uc3RhcnRzd2l0aChwcmVmaXgpIGZvciBwcmVmaXggaW4gKCIyMTExMzEiLCAiMjExMTMyIiwgIjIzMTEzIiwgIjIxMzIxIiAiMjMyMiIpKToKICAgICAgICAgICAgc3BsaXRfcG9pbnRzLmFwcGVuZChpKzEpCiAgICByZXR1cm4gbGlzdChzcGxpdF9hbG9uZyhzLCBzcGxpdF9wb2ludHMpKQoKZiA9IGxhbWJkYSBzOiAiIi5qb2luKHN0cihsZW4obGlzdCh2KSkpK2sgZm9yIGssdiBpbiBpdGVydG9vbHMuZ3JvdXBieShzKSkKCmRlZiBnKHMseCk6CiAgICBmb3IgaSBpbiByYW5nZSh4KToKICAgICAgICBzID0gZihzKQogICAgcmV0dXJuIHMKCmRlZiBzaG93X3NlcXVlbmNlKHMsIG1heCk6CiAgICBmb3IgeCBpbiByYW5nZShtYXgpOgogICAgICAgIHByaW50IGcocyx4KQoKbWluX3Zpc2l0ZWRfZGVwdGggPSBmbG9hdCgiaW5mIikKCkBtZW1vaXplCmRlZiBzaXplKHMsIG4sIG09Tm9uZSk6CiAgICBnbG9iYWwgbWluX3Zpc2l0ZWRfZGVwdGgKICAgIGlmIG4gPCBtaW5fdmlzaXRlZF9kZXB0aDoKICAgICAgICAjcHJpbnQgbiwKICAgICAgICBtaW5fdmlzaXRlZF9kZXB0aCA9IG4KCiAgICBpZiBsZW4ocykgPiAxMDA6CiAgICAgICAgcmFpc2UgRXhjZXB0aW9uKCJmYWlsZWQgdG8gY2xlYXZlIGVmZmljaWVudGx5IG9uIHt9Ii5mb3JtYXQocykpCiAgICBpZiBuID09IDA6CiAgICAgICAgcmV0dXJuIGxlbihzKQogICAgcGllY2VzID0gc3BlY2lhbF9wYXJ0aXRpb24ocykKICAgIHBpZWNlX3NpemVzID0gW3NpemUoZihwaWVjZSksIG4tMSwgbSkgZm9yIHBpZWNlIGluIHBpZWNlc10KICAgIHJlc3VsdCA9IHN1bShwaWVjZV9zaXplcykKICAgIGlmIG06IHJlc3VsdCA9IHJlc3VsdCAlIG0KICAgIHJldHVybiByZXN1bHQKICAgIAp0cnk6CiAgICBwcmludCBzaXplKCIzIiwgNTAwLCAxMDApCmV4Y2VwdCBFeGNlcHRpb24gYXMgZToKICAgIHByaW50IGUubWVzc2FnZQ==