Problem p02794 (python)

Fixed submission:
# -*- coding: utf-8 -*-

#############
# Libraries #
#############

import sys
input = sys.stdin.readline

import math
from collections import deque
from fractions import gcd
from functools import lru_cache


#############
# Constants #
#############

MOD = 10**9+7
INF = float('inf')

#############
# Functions #
#############

######INPUT######
def inputI(): return int(input().strip())
def inputS(): return input().strip()
def inputIL(): return list(map(int,input().split()))
def inputSL(): return list(map(str,input().split()))
def inputILs(n): return list(int(input()) for _ in range(n))
def inputSLs(n): return list(input().strip() for _ in range(n))
def inputILL(n): return [list(map(int, input().split())) for _ in range(n)]
def inputSLL(n): return [list(map(str, input().split())) for _ in range(n)]

#####Inverse#####
def inv(n): return pow(n, MOD-2, MOD)

######Combination######
kaijo_memo = []
def kaijo(n):
  if(len(kaijo_memo) > n):
    return kaijo_memo[n]
  if(len(kaijo_memo) == 0):
    kaijo_memo.append(1)
  while(len(kaijo_memo) <= n):
    kaijo_memo.append(kaijo_memo[-1] * len(kaijo_memo) % MOD)
  return kaijo_memo[n]

gyaku_kaijo_memo = []
def gyaku_kaijo(n):
  if(len(gyaku_kaijo_memo) > n):
    return gyaku_kaijo_memo[n]
  if(len(gyaku_kaijo_memo) == 0):
    gyaku_kaijo_memo.append(1)
  while(len(gyaku_kaijo_memo) <= n):
    gyaku_kaijo_memo.append(gyaku_kaijo_memo[-1] * pow(len(gyaku_kaijo_memo),MOD-2,MOD) % MOD)
  return gyaku_kaijo_memo[n]

def nCr(n,r):
  if(n == r):
    return 1
  if(n < r or r < 0):
    return 0
  ret = 1
  ret = ret * kaijo(n) % MOD
  ret = ret * gyaku_kaijo(r) % MOD
  ret = ret * gyaku_kaijo(n-r) % MOD
  return ret

######Factorization######
def factorization(n):
    arr = []
    temp = n
    for i in range(2, int(-(-n**0.5//1))+1):
        if temp%i==0:
            cnt=0
            while temp%i==0:
                cnt+=1
                temp //= i
            arr.append([i, cnt])
    if temp!=1:
        arr.append([temp, 1])

    if arr==[]:
        arr.append([n, 1])
    return arr

#####LCM#####
def lcm(a, b):
    return a * b // gcd (a, b)

#############
# Main Code #
#############

N = inputI()

graph = [[] for _ in range(N)]
edges = []
 
for _ in range(N - 1):
  a, b = inputIL()
  edges.append((a-1, b-1))
  
for a, b in edges:
  graph[a].append(b)
  graph[b].append(a)
  
  
M = inputI()
m = inputILL(M)

prv = [None for i in range(N)]

prv[0] = -1

q = deque([0])

while q:
  u = q.popleft()
  for v in graph[u]:
    if prv[v] == None:
      prv[v] = u
      q.append(v)

to_root = []

for i in range(N):
  s = 0
  now = i
  while now!=0:
    s += pow(2,now)
    now = prv[now]
  to_root.append(s)

  
ans = 0
for k in range(pow(2,M)):
  J = []
  for i in range(M):
    if k>>i & 1:
      J.append(m[i])
  mask = 0
  for u,v in J:
    mask |= to_root[u-1]^to_root[v-1]
  ##########
  count = 0
  while mask:
    mask &= mask -1
    count += 1
  ##########
  c = 0
  while k:
    k &= k -1
    c += 1
  sign = 1
  if c%2 == 1:
    sign = -1
  ###########
  ans += sign * pow(2,N-1-count)

print(ans)

Buggy submission (verdict: Runtime Error):
# -*- coding: utf-8 -*-

#############
# Libraries #
#############

import math
from functools import lru_cache

#############
# Constants #
#############

MOD = 10**9 +7
INF = float('inf')

#############
# Functions #
#############

def swap(x,y):
  return y,x

def count_ones_by_bin(n):
  bin_n = bin(n)[2:]
  count = 0
  for i in bin_n:
    count += int(i)
  return count

kaijo_memo = []
def kaijo(n):
  if(len(kaijo_memo) > n):
    return kaijo_memo[n]
  if(len(kaijo_memo) == 0):
    kaijo_memo.append(1)
  while(len(kaijo_memo) <= n):
    kaijo_memo.append(kaijo_memo[-1] * len(kaijo_memo) % MOD)
  return kaijo_memo[n]

gyaku_kaijo_memo = []
def gyaku_kaijo(n):
  if(len(gyaku_kaijo_memo) > n):
    return gyaku_kaijo_memo[n]
  if(len(gyaku_kaijo_memo) == 0):
    gyaku_kaijo_memo.append(1)
  while(len(gyaku_kaijo_memo) <= n):
    gyaku_kaijo_memo.append(gyaku_kaijo_memo[-1] * pow(len(gyaku_kaijo_memo),MOD-2,MOD) % MOD)
  return gyaku_kaijo_memo[n]

def nCr(n,r):
  if(n == r):
    return 1
  if(n < r or r < 0):
    return 0
  ret = 1
  ret = ret * kaijo(n) % MOD
  ret = ret * gyaku_kaijo(r) % MOD
  ret = ret * gyaku_kaijo(n-r) % MOD
  return ret

def factorization(n):
    arr = []
    temp = n
    for i in range(2, int(-(-n**0.5//1))+1):
        if temp%i==0:
            cnt=0
            while temp%i==0:
                cnt+=1
                temp //= i
            arr.append([i, cnt])
    if temp!=1:
        arr.append([temp, 1])

    if arr==[]:
        arr.append([n, 1])
    return arr

#############
# Main Code #
#############

N = int(input())
LOG_N = math.floor(math.log(N)/math.log(2))

#{node:[depth,ancestor]}
dic = {}
for i in range(N-1):
  a,b = list(map(int,input().split()))
  if i == 0:
    dic[a] = [0,-1]
  if a in dic:
    dic[b] = [dic[a][0]+1,a]
  else:
    dic[a] = [dic[b][0]+1,b]

#table[k][i]: i's 2^k-th ancestor
table = [[0 for i in range(N+1)] for j in range(LOG_N+1)] 

for i in range(1,N+1):
  table[0][i] = dic[i][1]

for k in range(LOG_N):
  for i in range(1,N+1):
    if (table[k][i] == -1):
      table[k+1][i] = -1
    else:
      table[k+1][i] = table[k][table[k][i]]

def lca(u,v):
  if dic[u][0] > dic[v][0]:
    u,v = swap(u,v)
  for i in range(LOG_N+1)[::-1]:
    if ((dic[v][0] - dic[u][0]) >> i) & 1:
      v = table[i][v]
  if u == v:
    return u
  for i in range(LOG_N+1)[::-1]:
    if table[i][u] != table[i][v]:
      u = table[i][u]
      v = table[i][v]
  return table[0][u]

#path to root
@lru_cache(maxsize=None)
def path_to_root(i):
  if i == 1:
    return 0
  return path_to_root(table[0][i])+2**i

M = int(input())
l = []
for i in range(M):
  l.append(tuple(map(int,input().split())))


accum = 2**(N-1)
for i in range(1,2**M):
  choice = []
  for j in range(M):
    if (i >> j) & 1:
      choice.append(l[j])
  cover = 0
  for item in choice:
    u = item[0]
    v = item[1]
    u_ = path_to_root(u) - path_to_root(lca(u,v))
    v_ = path_to_root(v) - path_to_root(lca(u,v))
    cover = cover | u_ | v_
  
  conditions = len(choice)
  paths = count_ones_by_bin(cover)
  
  accum += 2 ** (N-1-paths) * (((M-conditions)%2)*2-1)


    
print(accum)

Buggy submission (verdict: Runtime Error):
# -*- coding: utf-8 -*-

#############
# Libraries #
#############

import math
from functools import lru_cache

#############
# Constants #
#############

MOD = 10**9 +7
INF = float('inf')

#############
# Functions #
#############

def swap(x,y):
  return y,x

def count_ones_by_bin(n):
  bin_n = bin(n)[2:]
  count = 0
  for i in bin_n:
    count += int(i)
  return count

kaijo_memo = []
def kaijo(n):
  if(len(kaijo_memo) > n):
    return kaijo_memo[n]
  if(len(kaijo_memo) == 0):
    kaijo_memo.append(1)
  while(len(kaijo_memo) <= n):
    kaijo_memo.append(kaijo_memo[-1] * len(kaijo_memo) % MOD)
  return kaijo_memo[n]

gyaku_kaijo_memo = []
def gyaku_kaijo(n):
  if(len(gyaku_kaijo_memo) > n):
    return gyaku_kaijo_memo[n]
  if(len(gyaku_kaijo_memo) == 0):
    gyaku_kaijo_memo.append(1)
  while(len(gyaku_kaijo_memo) <= n):
    gyaku_kaijo_memo.append(gyaku_kaijo_memo[-1] * pow(len(gyaku_kaijo_memo),MOD-2,MOD) % MOD)
  return gyaku_kaijo_memo[n]

def nCr(n,r):
  if(n == r):
    return 1
  if(n < r or r < 0):
    return 0
  ret = 1
  ret = ret * kaijo(n) % MOD
  ret = ret * gyaku_kaijo(r) % MOD
  ret = ret * gyaku_kaijo(n-r) % MOD
  return ret

def factorization(n):
    arr = []
    temp = n
    for i in range(2, int(-(-n**0.5//1))+1):
        if temp%i==0:
            cnt=0
            while temp%i==0:
                cnt+=1
                temp //= i
            arr.append([i, cnt])
    if temp!=1:
        arr.append([temp, 1])

    if arr==[]:
        arr.append([n, 1])
    return arr

#############
# Main Code #
#############

N = int(input())
LOG_N = math.floor(math.log(N)/math.log(2))

#{node:[depth,ancestor]}
dic = {}
for i in range(N-1):
  a,b = list(map(int,input().split()))
  if i == 0:
    dic[a] = [0,-1]
  if a in dic:
    dic[b] = [dic[a][0]+1,a]
  else:
    dic[a] = [dic[b][0]+1,b]

#table[k][i]: i's 2^k-th ancestor
table = [[0 for i in range(N+1)] for j in range(LOG_N+1)] 

for i in range(1,N+1):
  table[0][i] = dic[i][1]

for k in range(LOG_N):
  for i in range(1,N+1):
    if (table[k][i] == -1):
      table[k+1][i] = -1
    else:
      table[k+1][i] = table[k][table[k][i]]

def lca(u,v):
  if dic[u][0] > dic[v][0]:
    u,v = swap(u,v)
  for i in range(LOG_N+1)[::-1]:
    if ((dic[v][0] - dic[u][0]) >> i) & 1:
      v = table[i][v]
  if u == v:
    return u
  for i in range(LOG_N)[::-1]:
    if table[i][u] != table[i][v]:
      u = table[i][u]
      v = table[i][v]
  return table[0][u]

#path to root
@lru_cache(maxsize=None)
def path_to_root(i):
  if i == 1:
    return 0
  return path_to_root(table[0][i])+2**i

M = int(input())
l = []
for i in range(M):
  l.append(tuple(map(int,input().split())))


accum = 2**(N-1)
for i in range(1,2**M):
  choice = []
  for j in range(M):
    if (i >> j) & 1:
      choice.append(l[j])
  cover = 0
  for item in choice:
    u = item[0]
    v = item[1]
    u_ = path_to_root(u) - path_to_root(lca(u,v))
    v_ = path_to_root(v) - path_to_root(lca(u,v))
    cover = cover | u_ | v_
  
  conditions = len(choice)
  paths = count_ones_by_bin(cover)
  
  accum += 2 ** (N-1-paths) * (((M-conditions)%2)*2-1)


    
print(accum)