제출 #1359402

#제출 시각아이디문제언어결과실행 시간메모리
1359402haireCutting a Rectangle (BOI24_rectangle)Pypy 3
25 / 100
2041 ms830092 KiB
import heapq

from collections import Counter


def gcd(x, y):
    """greatest common divisor of x and y"""
    while y:
        x, y = y, x % y
    return x


def memodict(f):
    """memoization decorator for a function taking a single argument"""
    class memodict(dict):
        def __missing__(self, key):
            ret = self[key] = f(key)
            return ret

    return memodict().__getitem__


def pollard_rho(n):
    """returns a random factor of n"""
    if n & 1 == 0:
        return 2
    if n % 3 == 0:
        return 3

    s = ((n - 1) & (1 - n)).bit_length() - 1
    d = n >> s
    for a in [2, 325, 9375, 28178, 450775, 9780504, 1795265022]:
        p = pow(a, d, n)
        if p == 1 or p == n - 1 or a % n == 0:
            continue
        for _ in range(s):
            prev = p
            p = (p * p) % n
            if p == 1:
                return gcd(prev - 1, n)
            if p == n - 1:
                break
        else:
            for i in range(2, n):
                x, y = i, (i * i + 1) % n
                f = gcd(abs(x - y), n)
                while f == 1:
                    x, y = (x * x + 1) % n, (y * y + 1) % n
                    y = (y * y + 1) % n
                    f = gcd(abs(x - y), n)
                if f != n:
                    return f
    return n


@memodict
def prime_factors(n):
    """returns a Counter of the prime factorization of n"""
    if n <= 1:
        return Counter()
    f = pollard_rho(n)
    return Counter([n]) if f == n else prime_factors(f) + prime_factors(n // f)


def distinct_factors(n):
    """returns a list of all distinct factors of n"""
    factors = [1]
    for p, exp in prime_factors(n).items():
        factors += [p**i * factor for factor in factors for i in range(1, exp + 1)]
    return factors


def all_factors(n):
    """returns a sorted list of all distinct factors of n"""
    small, large = [], []
    for i in range(1, int(n**0.5) + 1, 2 if n & 1 else 1):
        if not n % i:
            small.append(i)
            large.append(n // i)
    if small[-1] == large[-1]:
        large.pop()
    large.reverse()
    small.extend(large)
    return small

n = int(input())
tot = 0
things = []
bound = 0

allsides = set()

for _ in range(n):
    a,b = map(int,input().split())
    tot += a*b
    bound = max(bound,a,b)
    things.append((a,b))
    allsides.add(a)
    allsides.add(b)



ans = []

cands = distinct_factors(tot)
cands.sort()
cands = cands[:(len(cands)+1)//2]
#print(cands,tot)
while tot//cands[-1] < bound:
    cands.pop()

#print(cands,things)

cands2 = []

for c in cands:
    x,y = c, tot//c
    if x not in allsides and y not in allsides:
        continue
    
    for a,b in things:
        #print(a,b,x,y)
        if min(a,b) <= min(x,y) and max(a,b) <= max(x,y):
            continue
        break
    else:
        cands2.append(c)

#print(cands2)

if len(cands2) == 1:
    print(1)
    print(cands2[0])
    exit()


for c in cands2:
    x,y = c, tot//c

    # if K <= 10, have a bitset BFS

    # if b = 1, greedy
    used = [0]*n
    thingInd = {}
    for i,(a,b) in enumerate(things):
        if a not in thingInd:
            thingInd[a] = []
        if b not in thingInd:
            thingInd[b] = []
        
        if a == b:
            heapq.heappush(thingInd[a],(-a,i))
        else:
            heapq.heappush(thingInd[a],(-a,i))
            heapq.heappush(thingInd[b],(-a,i))



    bad = 0
    while x>1 and y>1:

        found = -1
        if x in thingInd:
            
            while thingInd[x]:
                xa,temp = thingInd[x][0]
                xa *= -1

                if not used[temp]:
                    found = (xa,temp,0)
                    break
                else:
                    heapq.heappop(thingInd[x])
                
            
        
        if y in thingInd:
            while thingInd[y]:
                ya,temp = thingInd[y][0]
                ya *= -1

                if not used[temp]:
                    if found == -1:
                        found = (ya,temp,1)
                    else:
                        if ya > found[0]:
                            found = (ya,temp,1)
                    break
                else:
                    heapq.heappop(thingInd[y])
        
        
        if found == -1:
            bad = 1
            break
        
        if found[2]:
            heapq.heappop(thingInd[y])
        else:
            heapq.heappop(thingInd[x])

        found = found[1]

        a,b = things[found]
        used[found] = 1

        if a == x and b <= y:
            y -= b
        elif b == x and a <= y:
            y -= a
        elif a == y and b <= x:
            x -= b
        elif b == y and a <= x:
            x -= a
        else:
            bad = 1
            break
    
    if bad:
        continue
    if x == 0 or y == 0:
        ans.append(c)
        #print(used)
        #assert(min(used) == 1)
        continue
    
    if x == 1 or y == 1:
        s = x+y-1
        t = 0
        if 1 not in thingInd:
            continue
        for _,ind in thingInd[1]:
            if not used[ind]:
                a,b = things[ind]
                t += a+b-1
        
        if t == s:
            ans.append(c)
            continue
    
print(len(ans))

for x in ans:
    print(x)

    


컴파일 시 표준 출력 (stdout) 메시지

Compiling 'Main.py'...

=======
  adding: __main__.pyc (deflated 45%)

=======
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...