結果
問題 | No.30 たこやき工場 |
ユーザー |
|
提出日時 | 2023-09-24 08:33:13 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 106 ms / 5,000 ms |
コード長 | 19,099 bytes |
コンパイル時間 | 158 ms |
コンパイル使用メモリ | 82,140 KB |
実行使用メモリ | 79,464 KB |
最終ジャッジ日時 | 2024-07-17 08:55:56 |
合計ジャッジ時間 | 2,324 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 17 |
ソースコード
from collections import *from bisect import *from math import *from heapq import *from itertools import *def popcount(n):c=(n&0x5555555555555555)+((n>>1)&0x5555555555555555)c=(c&0x3333333333333333)+((c>>2)&0x3333333333333333)c=(c&0x0f0f0f0f0f0f0f0f)+((c>>4)&0x0f0f0f0f0f0f0f0f)c=(c&0x00ff00ff00ff00ff)+((c>>8)&0x00ff00ff00ff00ff)c=(c&0x0000ffff0000ffff)+((c>>16)&0x0000ffff0000ffff)c=(c&0x00000000ffffffff)+((c>>32)&0x00000000ffffffff)return c"""mod = 10**9+7M= (10**5)*3+1fac= [1]*Mninv= [1]*Mfinv= [1]*Mfor i in range(2,M):fac[i] = fac[i-1]*i%modninv[i] = (-(mod//i)*ninv[mod%i])%modfinv[i] = finv[i-1]*ninv[i]%moddef binom(n,k):if n<0 or k<0:return 0if k>n:return 0return (fac[n]*finv[k]%mod)*finv[n-k]%moddef nHk(n, k):return binom(n + k - 1, k)"""def nCk(n, k):k = min(k, n - k)ret = 1for i in range(n, n - k, -1): ret *= ifor i in range(2, k + 1): ret //= ireturn retdef nHk(n, k):return nCk(n + k - 1, k)def nC2(x):return x*(x-1)//2def is_prime(n):if n == 1: return Falsefor k in range(2, int(math.sqrt(n)) + 1):if n % k == 0:return Falsereturn Trueclass UnionFind():def __init__(self, n):self.n = nself.parents = [-1] * nself.group = ndef find(self, x):if self.parents[x] < 0:return xelse:self.parents[x] = self.find(self.parents[x])return self.parents[x]def union(self, x, y):x = self.find(x)y = self.find(y)if x == y:returnself.group -= 1if self.parents[x] > self.parents[y]:x, y = y, xself.parents[x] += self.parents[y]self.parents[y] = xdef size(self, x):return -self.parents[self.find(x)]def same(self, x, y):return self.find(x) == self.find(y)def members(self, x):root = self.find(x)return [i for i in range(self.n) if self.find(i) == root]def roots(self):return [i for i, x in enumerate(self.parents) if x < 0]def group_count(self):return self.groupdef all_group_members(self):dic = {r:[] for r in self.roots()}for i in range(self.n):dic[self.find(i)].append(i)return dicdef __str__(self):return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())class SOE:def __init__(self,m):self.sieve=[-1]*(m+1)self.prime=[]for i in range(2,m+1):if self.sieve[i]==-1:self.prime.append(i)self.sieve[i]=ij=2*iwhile j<=m:self.sieve[j]=ij+=idef primes(self):# get primesreturn self.primedef fact(self,n):# prime factorizationd=[]while n!=1:p=self.sieve[n]d.append(p)while n%p==0:n//=preturn ddef div(n):lower,upper = [],[]i = 1while i*i <= n:if n%i == 0:lower.append(i)if i!=n//i:upper.append(n//i)i += 1return lower+upper[::-1]def factorize(x):yaku = []for i in range(2,int(x**0.5)+1):if x%i == 0:while x%i == 0:x //= iyaku.append(i)if x != 1:yaku.append(x)return yaku#[2,3]この形def fact(n):res=na=[]i=2while i*i<=res:if res%i==0:cnt=0while res%i==0:cnt+=1res//=ia.append((i,cnt))i+=1if res!=1:a.append((res,1))return a"""[(2, 1), (3, 1)]この形"""def nc2(x):return (x*(x-1)//2)import randomclass RollingHash:mask30 = (1 << 30) - 1mask31 = (1 << 31) - 1MOD = (1 << 61) - 1Base = Nonepw = [1]def __init__(self, S):if RollingHash.Base is None:RollingHash.Base = random.randrange(129, 1 << 30)for i in range(len(RollingHash.pw), len(S) + 1):RollingHash.pw.append(RollingHash.CalcMod(RollingHash.Mul(RollingHash.pw[i - 1], self.__class__.Base)))self.hash = [0] * (len(S) + 1)for i, s in enumerate(S, 1):self.hash[i] = RollingHash.CalcMod(RollingHash.Mul(self.hash[i - 1], RollingHash.Base) + ord(s))def get(self, l, r):return RollingHash.CalcMod(self.hash[r] - RollingHash.Mul(self.hash[l], RollingHash.pw[r - l]))def Mul(l, r):lu = l >> 31ld = l & RollingHash.mask31ru = r >> 31rd = r & RollingHash.mask31middlebit = ld * ru + lu * rdreturn ((lu * ru) << 1) + ld * rd + \((middlebit & RollingHash.mask30) << 31) + (middlebit >> 30)def CalcMod(val):if val < 0:val %= RollingHash.MODval = (val & RollingHash.MOD) + (val >> 61)if val > RollingHash.MOD:val -= RollingHash.MODreturn val# https://github.com/tatyam-prime/SortedSet/blob/main/SortedMultiset.pyimport mathfrom bisect import bisect_left, bisect_right, insortfrom typing import Generic, Iterable, Iterator, TypeVar, Optional, ListT = TypeVar('T')class SortedMultiset(Generic[T]):BUCKET_RATIO = 50REBUILD_RATIO = 170def _build(self, a=None) -> None:"Evenly divide `a` into buckets."if a is None: a = list(self)size = self.size = len(a)bucket_size = int(math.ceil(math.sqrt(size / self.BUCKET_RATIO)))self.a = [a[size * i // bucket_size : size * (i + 1) // bucket_size] for i in range(bucket_size)]def __init__(self, a: Iterable[T] = []) -> None:"Make a new SortedMultiset from iterable. / O(N) if sorted / O(N log N)"a = list(a)if not all(a[i] <= a[i + 1] for i in range(len(a) - 1)):a = sorted(a)self._build(a)def __iter__(self) -> Iterator[T]:for i in self.a:for j in i: yield jdef __reversed__(self) -> Iterator[T]:for i in reversed(self.a):for j in reversed(i): yield jdef __len__(self) -> int:return self.sizedef __repr__(self) -> str:return "SortedMultiset" + str(self.a)def __str__(self) -> str:s = str(list(self))return "{" + s[1 : len(s) - 1] + "}"def _find_bucket(self, x: T) -> List[T]:"Find the bucket which should contain x. self must not be empty."for a in self.a:if x <= a[-1]: return areturn adef __contains__(self, x: T) -> bool:if self.size == 0: return Falsea = self._find_bucket(x)i = bisect_left(a, x)return i != len(a) and a[i] == xdef count(self, x: T) -> int:"Count the number of x."return self.index_right(x) - self.index(x)def add(self, x: T) -> None:"Add an element. / O(√N)"if self.size == 0:self.a = [[x]]self.size = 1returna = self._find_bucket(x)insort(a, x)self.size += 1if len(a) > len(self.a) * self.REBUILD_RATIO:self._build()def discard(self, x: T) -> bool:"Remove an element and return True if removed. / O(√N)"if self.size == 0: return Falsea = self._find_bucket(x)i = bisect_left(a, x)if i == len(a) or a[i] != x: return Falsea.pop(i)self.size -= 1if len(a) == 0: self._build()return Truedef lt(self, x: T) -> Optional[T]:"Find the largest element < x, or None if it doesn't exist."for a in reversed(self.a):if a[0] < x:return a[bisect_left(a, x) - 1]def le(self, x: T) -> Optional[T]:"Find the largest element <= x, or None if it doesn't exist."for a in reversed(self.a):if a[0] <= x:return a[bisect_right(a, x) - 1]def gt(self, x: T) -> Optional[T]:"Find the smallest element > x, or None if it doesn't exist."for a in self.a:if a[-1] > x:return a[bisect_right(a, x)]def ge(self, x: T) -> Optional[T]:"Find the smallest element >= x, or None if it doesn't exist."for a in self.a:if a[-1] >= x:return a[bisect_left(a, x)]def __getitem__(self, x: int) -> T:"Return the x-th element, or IndexError if it doesn't exist."if x < 0: x += self.sizeif x < 0: raise IndexErrorfor a in self.a:if x < len(a): return a[x]x -= len(a)raise IndexErrordef index(self, x: T) -> int:"Count the number of elements < x."ans = 0for a in self.a:if a[-1] >= x:return ans + bisect_left(a, x)ans += len(a)return ansdef index_right(self, x: T) -> int:"Count the number of elements <= x."ans = 0for a in self.a:if a[-1] > x:return ans + bisect_right(a, x)ans += len(a)return ansoo = 1<<60ans = 0cnt = 0res = oodef dijkstra(n, s, G):hq = [(0, s)]cost = [float('inf')] * ncost[s] = 0while hq:c,v = heappop(hq)if c > cost[v]:continuefor nv,d in G[v]:tmp = d + cost[v]if tmp < cost[nv]:cost[nv] = tmpheappush(hq, (tmp,nv))return costclass Topological_Sort:def __init__(self, N: int):""" N 頂点からなる空グラフを用意する.N: int"""self.N=Nself.arc=[[] for _ in range(N)]self.rev=[[] for _ in range(N)]def add_arc(self, source: int, target: int):""" 有向辺 source → taeget を追加する."""self.arc[source].append(target)self.rev[target].append(source)def sort(self):""" トポロジカルソートを求める.[Ouput]存在する → トポロジカルソート存在しない → None"""in_deg=[len(self.rev[x]) for x in range(self.N)]Q=[x for x in range(self.N) if in_deg[x]==0]S=[]while Q:u=Q.pop()S.append(u)for v in self.arc[u]:in_deg[v]-=1if in_deg[v]==0:Q.append(v)return S if len(S)==self.N else Nonedef is_DAG(self):""" DAG かどうかを判定する."""return self.sort()!=None"""class LowestCommonAncestor:def __init__(self,n):self._n=n;n=0while 2**(n/10)<self._n:n+=1self._logn=int(n/10+2) #mathモジュールなしで構築self._depth= [ 0 for _ in [0]*self._n]self._distance= [ 0 for _ in [0]*self._n]self._ancestor=[[-1 for _ in [0]*self._n] for k in [0]*self._logn]self._edge= [[] for _ in [0]*self._n]def add_edge(self,u,v,w=1): #頂点u,v間に重みwの辺を追加するself._edge[u].append((v,w))self._edge[v].append((u,w))def build(self,root=0): #rootを指定し、その他の頂点に祖先情報を書き込むstack=[root]while stack:now=stack.pop()for nxt,w in self._edge[now]:if self._ancestor[0][nxt]!=now and self._ancestor[0][now]!=nxt:self._ancestor[0][nxt]=nowself._depth[nxt]= self._depth[now] +1self._distance[nxt]=self._distance[now]+wstack.append(nxt)for k in range(1,self._logn):for i in range(self._n):if self._ancestor[k-1][i]==-1:self._ancestor[k][i]=-1else:self._ancestor[k][i]=self._ancestor[k-1][self._ancestor[k-1][i]]def LCA(self,u,v):if self._depth[u]>self._depth[v]:u,v=v,u #uが浅く、vが深い状態にfor k in range(self._logn-1,-1,-1): #vとuを同じ深度にif ((self._depth[v]-self._depth[u])>>k)&1:v=self._ancestor[k][v]if u==v:return ufor k in range(self._logn-1,-1,-1): #ギリギリ一致する直前まで祖先を辿るif self._ancestor[k][u]!=self._ancestor[k][v]:u,v=self._ancestor[k][u],self._ancestor[k][v]return self._ancestor[0][u]def distance(self,u,v):return self._distance[u]+self._distance[u]-2*self._distance[self.LCA(u,v)]"""import mathclass LCA:def __init__(self,n):self._n=nself._logn=int(math.log2(self._n)+2)self._depth=[0]*self._nself._distance=[0]*self._nself._ancestor=[[-1]*self._n for k in range(self._logn)]self._edges=[[] for i in range(self._n)]def add_edge(self,u,v,w=1):self._edges[u].append((v,w))self._edges[v].append((u,w))def build(self,root=0):stack=[root]while len(stack):cur = stack.pop()for nxt,w in self._edges[cur]:if self._ancestor[0][nxt]!=cur and self._ancestor[0][cur]!=nxt:self._ancestor[0][nxt]=curself._depth[nxt]=self._depth[cur]+1self._distance[nxt]=self._distance[cur]+wstack.append(nxt)for k in range(1,self._logn):for i in range(self._n):if self._ancestor[k-1][i]==-1:self._ancestor[k][i]=-1else:self._ancestor[k][i]=self._ancestor[k-1][self._ancestor[k-1][i]]def lca(self,u,v):if self._depth[u]>self._depth[v]:u,v=v,ufor k in range(self._logn-1,-1,-1):if ((self._depth[v]-self._depth[u])>>k)&1:v=self._ancestor[k][v]if u==v:return ufor k in range(self._logn-1,-1,-1):if self._ancestor[k][u]!=self._ancestor[k][v]:u=self._ancestor[k][u]v=self._ancestor[k][v]return self._ancestor[0][u]def distance(self,u,v):return self._distance[u]+self._distance[v]-2*self._distance[self.lca(u,v)]class BIT_SortedSet:def __init__(self, A, compress=True, sort_flag=False):self.compress = compressself.N = len(A)self.log = 0while self.N >= 1 << (self.log + 1):self.log += 1if compress:if sort_flag:self.A = Aelse:self.A = sorted(A)self.index_dic = {}for i in range(len(A)):self.index_dic[self.A[i]] = ielse:self.A = Aself.BIT = [0] * (self.N + 5)self.size = 0self.cnt = [0] * self.Ndef BIT_add(self, i, x):idx = i + 1while idx < self.N + 1:self.BIT[idx] += xidx += idx & (-idx)def BIT_query(self, i):res = 0idx = i + 1while idx:res += self.BIT[idx]idx -= idx & (-idx)return resdef BIT_lower_left(self, w):if w <= 0 or w > self.size:return Nonex = 0k = 1 << self.logwhile k > 0:if x + k < self.N and self.BIT[x + k] < w:w -= self.BIT[x + k]x += kk //= 2return xdef __contains__(self, x):if self.compress:x = self.index_dic[x]return self.cnt[x] >= 1def __len__(self):return self.sizedef add(self, x):if self.compress:x = self.index_dic[x]if self.cnt[x] == 1:return Falseself.BIT_add(x, 1)self.size += 1self.cnt[x] += 1return Truedef discard(self, x):if self.compress:x = self.index_dic[x]if self.cnt[x] > 0:self.BIT_add(x, -1)self.size -= 1self.cnt[x] -= 1return Truereturn Falsedef find_kth_val(self, k):res = self.BIT_lower_left(k + 1)if res == None:return Noneif self.compress:res = self.A[res]return resdef __getitem__(self, x):if x < 0:x += self.sizeif x < 0 or x >= self.size:raise IndexErrorreturn self.find_kth_val(x)def index_right(self, x):if x < self.A[0]:return 0if self.compress:y = bisect.bisect_right(self.A, x) - 1else:y = min(x, self.N - 1)return self.BIT_query(y)def index(self, x):if x <= self.A[0]:return 0if self.compress:y = bisect.bisect_right(self.A, x) - 1else:y = xif y >= self.N:y = self.N - 1elif self.A[y] == x:y -= 1return self.BIT_query(y)def gt(self, x):return self.find_kth_val(self.index_right(x))def ge(self, x):return self.find_kth_val(self.index(x))def lt(self, x):return self.find_kth_val(self.index(x) - 1)def le(self, x):return self.find_kth_val(self.index_right(x) - 1)def __str__(self):return ("{"+ ", ".join(map(str, [self.find_kth_val(i) for i in range(self.size)]))+ "}")def find_cycle(n,edge):seen=[0]*nfinished=[0]*nstc=[]for i in range(n):if seen[i]:continuetodo=[(1,i,-1),(0,i,-1)]seen[i]=Truewhile todo:t,v,edge_id=todo.pop()if t==0:if finished[v]:continueseen[v]=1stc.append((v,edge_id))for u,id in edge[v]:if finished[v]:continueif seen[u] and finished[u]==0:cyc=[id]while stc:v,id=stc.pop()if v==u:breakcyc.append(id)return cyc[::-1]elif seen[u]==0:todo.append((1,u,id))todo.append((0,u,id))else:if finished[v]:continuestc.pop()finished[v]=1return []import sysif sys.platform =='ios':import clipboarda=clipboard.get()a = a.split('\n')text = '\n'.join(a)with open('input_file.txt','w') as f:f.write(text)sys.stdin = open('input_file.txt')sys.setrecursionlimit(410000000)stdin = sys.stdindef ni():return int(ns())def na():return list(map(int, stdin.readline().split()))def ns():return stdin.readline().strip()def nm():return map(int,input().split())def na_1():return list(map(lambda x:int(x)*(-1), stdin.readline().split()))def na_2():return list(map(lambda x:int(x)-1, stdin.readline().split()))rnage=rangernge=rangerage = rangeN = ni()M = ni()ind = [0]*NG = [[]for i in range(N)]for i in range(M):p,x,q = nm()G[q-1].append((p-1,x))ind[p-1] += 1todo = []for i in range(N):if ind[i] == 0:todo.append(i)dp = [0]*Ndp[N-1] = 1ans = [0]*Nwhile todo:v = todo.pop()if len(G[v]) == 0:ans[v] = dp[v]for nv,c in G[v]:dp[nv] += dp[v]*cind[nv] -= 1if ind[nv] == 0:todo.append(nv)print(*ans[:-1],sep="\n")