結果
問題 | No.42 貯金箱の溜息 |
ユーザー |
![]() |
提出日時 | 2021-08-21 07:43:30 |
言語 | Python3 (3.13.1 + numpy 2.2.1 + scipy 1.14.1) |
結果 |
AC
|
実行時間 | 676 ms / 5,000 ms |
コード長 | 20,432 bytes |
コンパイル時間 | 139 ms |
コンパイル使用メモリ | 14,848 KB |
実行使用メモリ | 14,336 KB |
最終ジャッジ日時 | 2024-10-14 16:23:03 |
合計ジャッジ時間 | 3,288 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 3 |
ソースコード
import bisectimport copyimport decimalimport fractionsimport functoolsimport heapqimport itertoolsimport mathimport randomimport sysfrom collections import Counter,deque,defaultdictfrom functools import lru_cache,reducefrom heapq import heappush,heappop,heapify,heappushpop,_heappop_max,_heapify_maxdef _heappush_max(heap,item):heap.append(item)heapq._siftdown_max(heap, 0, len(heap)-1)def _heappushpop_max(heap, item):if heap and item < heap[0]:item, heap[0] = heap[0], itemheapq._siftup_max(heap, 0)return itemfrom math import degrees, gcd as GCDread=sys.stdin.readreadline=sys.stdin.readlinereadlines=sys.stdin.readlinesdef Extended_Euclid(n,m):stack=[]while m:stack.append((n,m))n,m=m,n%mif n>=0:x,y=1,0else:x,y=-1,0for i in range(len(stack)-1,-1,-1):n,m=stack[i]x,y=y,x-(n//m)*yreturn x,yclass MOD:def __init__(self,mod):self.mod=moddef Pow(self,a,n):a%=self.modif n>=0:return pow(a,n,self.mod)else:assert math.gcd(a,self.mod)==1x=Extended_Euclid(a,self.mod)[0]return pow(x,-n,self.mod)def Build_Fact(self,N):assert N>=0self.factorial=[1]for i in range(1,N+1):self.factorial.append((self.factorial[-1]*i)%self.mod)self.factorial_inv=[None]*(N+1)self.factorial_inv[-1]=self.Pow(self.factorial[-1],-1)for i in range(N-1,-1,-1):self.factorial_inv[i]=(self.factorial_inv[i+1]*(i+1))%self.modreturn self.factorial_invdef Fact(self,N):return self.factorial[N]def Fact_Inv(self,N):return self.factorial_inv[N]def Comb(self,N,K):if K<0 or K>N:return 0s=self.factorial[N]s=(s*self.factorial_inv[K])%self.mods=(s*self.factorial_inv[N-K])%self.modreturn sclass Lagrange_Interpolation:def __init__(self,X=False,Y=False,x0=None,xd=None,mod=0):self.degree=len(Y)-1self.mod=modassert self.degree<self.modif x0!=None and xd!=None:assert xd>0self.X=[(x0+i*xd)%self.mod for i in range(self.degree+1)]fact_inve=1for i in range(1,self.degree+1):fact_inve*=i*xdfact_inve%=self.modfact_inve=MOD(self.mod).Pow(fact_inve,-1)self.coefficient=[y for y in Y]for i in range(self.degree-1,-1,-2):self.coefficient[i]*=-1for i in range(self.degree,-1,-1):self.coefficient[i]*=fact_inveself.coefficient[i]%=self.modself.coefficient[self.degree-i]*=fact_inveself.coefficient[self.degree-i]%=self.modfact_inve*=i*xdfact_inve%=self.modelse:self.X=Xassert len(self.X)==self.degree+1self.coefficient=[y for y in Y]for i in range(self.degree+1):for j in range(self.degree+1):if i==j:continueself.coefficient[i]*=X[i]-X[j]self.coefficient%=self.moddef __getitem__(self,N):N%=self.modXX=[N-x for x in self.X]XX_left=[1]*(self.degree+2)for i in range(1,self.degree+2):XX_left[i]=XX_left[i-1]*XX[i-1]%self.modXX_right=[1]*(self.degree+2)for i in range(self.degree,-1,-1):XX_right[i]=XX_right[i+1]*XX[i]%self.modreturn sum(XX_left[i]*XX_right[i+1]*self.coefficient[i] for i in range(self.degree+1))%self.moddef NTT(polynomial1,polynomial2):prim_root=3prim_root_inve=MOD(mod).Pow(prim_root,-1)def DFT(polynomial,inverse=False):dft=polynomial+[0]*((1<<n)-len(polynomial))if inverse:for bit in range(1,n+1):a=1<<bit-1x=pow(prim_root,mod-1>>bit,mod)U=[1]for _ in range(a):U.append(U[-1]*x%mod)for i in range(1<<n-bit):for j in range(a):s=i*2*a+jt=s+adft[s],dft[t]=(dft[s]+dft[t]*U[j])%mod,(dft[s]-dft[t]*U[j])%modelse:for bit in range(n,0,-1):a=1<<bit-1x=pow(prim_root_inve,mod-1>>bit,mod)U=[1]for _ in range(a):U.append(U[-1]*x%mod)for i in range(1<<n-bit):for j in range(a):s=i*2*a+jt=s+adft[s],dft[t]=(dft[s]+dft[t])%mod,U[j]*(dft[s]-dft[t])%modreturn dftN=len(polynomial1)+len(polynomial2)-1n=(N-1).bit_length()ntt=[x*y%mod for x,y in zip(DFT(polynomial1),DFT(polynomial2))]ntt=DFT(ntt,inverse=True)x=pow((mod+1)//2,n)ntt=[ntt[i]*x%mod for i in range(N)]return nttdef FFT(polynomial1,polynomial2,digit=10**5):def DFT(polynomial,n,inverse=False):N=len(polynomial)if inverse:primitive_root=[math.cos(-i*2*math.pi/(1<<n))+math.sin(-i*2*math.pi/(1<<n))*1j for i in range(1<<n)]else:primitive_root=[math.cos(i*2*math.pi/(1<<n))+math.sin(i*2*math.pi/(1<<n))*1j for i in range(1<<n)]dft=polynomial+[0]*((1<<n)-N)if inverse:for bit in range(1,n+1):a=1<<bit-1for i in range(1<<n-bit):for j in range(a):s=i*2*a+jt=s+adft[s],dft[t]=dft[s]+dft[t]*primitive_root[j<<n-bit],dft[s]-dft[t]*primitive_root[j<<n-bit]else:for bit in range(n,0,-1):a=1<<bit-1for i in range(1<<n-bit):for j in range(a):s=i*2*a+jt=s+adft[s],dft[t]=dft[s]+dft[t],primitive_root[j<<n-bit]*(dft[s]-dft[t])return dftdef FFT_(polynomial1,polynomial2):N1=len(polynomial1)N2=len(polynomial2)N=N1+N2-1n=(N-1).bit_length()fft=[x*y for x,y in zip(DFT(polynomial1,n),DFT(polynomial2,n))]fft=DFT(fft,n,inverse=True)fft=[round((fft[i]/(1<<n)).real) for i in range(N)]return fftN1=len(polynomial1)N2=len(polynomial2)N=N1+N2-1polynomial11,polynomial12=[None]*N1,[None]*N1polynomial21,polynomial22=[None]*N2,[None]*N2for i in range(N1):polynomial11[i],polynomial12[i]=divmod(polynomial1[i],digit)for i in range(N2):polynomial21[i],polynomial22[i]=divmod(polynomial2[i],digit)polynomial=[0]*(N)a=digit**2-digitfor i,x in enumerate(FFT_(polynomial11,polynomial21)):polynomial[i]+=x*aa=digit-1for i,x in enumerate(FFT_(polynomial12,polynomial22)):polynomial[i]-=x*afor i,x in enumerate(FFT_([x1+x2 for x1,x2 in zip(polynomial11,polynomial12)],[x1+x2 for x1,x2 in zip(polynomial21,polynomial22)])):polynomial[i]+=x*digitreturn polynomialdef Primitive_Root(p):if p==2:return 1if p==167772161:return 3if p==469762049:return 3if p==754974721:return 11if p==998244353:return 3if p==10**9+7:return 5divisors=[2]pp=(p-1)//2while pp%2==0:pp//=2for d in range(3,pp+1,2):if d**2>pp:breakif pp%d==0:divisors.append(d)while pp%d==0:pp//=dif pp>1:divisors.append(pp)primitive_root=2while True:for d in divisors:if pow(primitive_root,(p-1)//d,p)==1:breakelse:return primitive_rootprimitive_root+=1class Polynomial:def __init__(self,polynomial,max_degree=-1,eps=1e-12,mod=0):self.max_degree=max_degreeif self.max_degree!=-1 and len(polynomial)>self.max_degree+1:self.polynomial=polynomial[:self.max_degree+1]else:self.polynomial=polynomialself.mod=modself.eps=epsdef __eq__(self,other):if type(other)!=Polynomial:return Falseif len(self.polynomial)!=len(other.polynomial):return Falsefor i in range(len(self.polynomial)):if abs(self.polynomial[i]-other.polynomial[i])>self.eps:return Falsereturn Truedef __ne__(self,other):if type(other)!=Polynomial:return Trueif len(self.polynomial)!=len(other.polynomial):return Truefor i in range(len(self.polynomial)):if abs(self.polynomial[i]-other.polynomial[i])>self.eps:return Truereturn Falsedef __add__(self,other):assert type(other)==Polynomialsumm=[0]*max(len(self.polynomial),len(other.polynomial))for i in range(len(self.polynomial)):summ[i]+=self.polynomial[i]for i in range(len(other.polynomial)):summ[i]+=other.polynomial[i]if self.mod:for i in range(len(summ)):summ[i]%=self.modwhile summ and abs(summ[-1])<self.eps:summ.pop()summ=Polynomial(summ,max_degree=self.max_degree,eps=self.eps,mod=self.mod)return summdef __sub__(self,other):assert type(other)==Polynomialdiff=[0]*max(len(self.polynomial),len(other.polynomial))for i in range(len(self.polynomial)):diff[i]+=self.polynomial[i]for i in range(len(other.polynomial)):diff[i]-=other.polynomial[i]if self.mod:for i in range(len(diff)):diff[i]%=self.modwhile diff and abs(diff[-1])<self.eps:diff.pop()diff=Polynomial(diff,max_degree=self.max_degree,eps=self.eps,mod=self.mod)return diffdef __mul__(self,other):if type(other)==Polynomial:if self.max_degree==-1:prod=[0]*(len(self.polynomial)+len(other.polynomial)-1)for i in range(len(self.polynomial)):for j in range(len(other.polynomial)):prod[i+j]+=self.polynomial[i]*other.polynomial[j]else:prod=[0]*min(len(self.polynomial)+len(other.polynomial)-1,self.max_degree+1)for i in range(len(self.polynomial)):for j in range(min(len(other.polynomial),self.max_degree+1-i)):prod[i+j]+=self.polynomial[i]*other.polynomial[j]if self.mod:for i in range(len(prod)):prod[i]%=self.modwhile prod and abs(prod[-1])<self.eps:prod.pop()else:if self.mod:prod=[x*other%self.mod for x in self.polynomial]else:prod=[x*other for x in self.polynomial]while prod and abs(prod[-1])<self.eps:prod.pop()prod=Polynomial(prod,max_degree=self.max_degree,eps=self.eps,mod=self.mod)return proddef __matmul__(self,other):assert type(other)==Polynomialif self.mod:prod=NTT(self.polynomial,other.polynomial)else:prod=FFT(self.polynomial,other.polynomial)if self.max_degree!=-1 and len(prod)>self.max_degree+1:prod=prod[:self.max_degree+1]while prod and abs(prod[-1])<self.eps:prod.pop()prod=Polynomial(prod,max_degree=self.max_degree,eps=self.eps,mod=self.mod)return proddef __truediv__(self,other):if type(other)==Polynomial:assert other.polynomialfor n in range(len(other.polynomial)):if self.eps<abs(other.polynomial[n]):breakassert len(self.polynomial)>nfor i in range(n):assert abs(self.polynomial[i])<self.epsself_polynomial=self.polynomial[n:]other_polynomial=other.polynomial[n:]if self.mod:inve=MOD(self.mod).Pow(other_polynomial[0],-1)else:inve=1/other_polynomial[0]quot=[]for i in range(len(self_polynomial)-len(other_polynomial)+1):if self.mod:quot.append(self_polynomial[i]*inve%self.mod)else:quot.append(self_polynomial[i]*inve)for j in range(len(other_polynomial)):self_polynomial[i+j]-=other_polynomial[j]*quot[-1]if self.mod:self_polynomial[i+j]%=self.modfor i in range(len(self_polynomial)-len(other_polynomial)+1,len(self_polynomial)):if self.eps<abs(self_polynomial[i]):assert self.max_degree!=-1self_polynomial=self_polynomial[-len(other_polynomial)+1:]while len(quot)<=self.max_degree:self_polynomial.append(0)if self.mod:quot.append(self_polynomial[0]*inve%self.mod)self_polynomial=[(self_polynomial[i]-other_polynomial[i]*quot[-1])%self.mod for i in range(1,len(self_polynomial))]else:quot.append(self_polynomial[0]*inve)self_polynomial=[(self_polynomial[i]-other_polynomial[i]*quot[-1]) for i in range(1,len(self_polynomial))]breakquot=Polynomial(quot,max_degree=self.max_degree,eps=self.eps,mod=self.mod)else:assert self.eps<abs(other)if self.mod:inve=MOD(self.mod).Pow(other,-1)quot=Polynomial([x*inve%self.mod for x in self.polynomial],max_degree=self.max_degree,eps=self.eps,mod=self.mod)else:quot=Polynomial([x/other for x in self.polynomial],max_degree=self.max_degree,eps=self.eps,mod=self.mod)return quotdef __floordiv__(self,other):assert type(other)==Polynomialquot=[0]*(len(self.polynomial)-len(other.polynomial)+1)rema=[x for x in self.polynomial]if self.mod:inve=MOD(self.mod).Pow(other.polynomial[-1],-1)for i in range(len(self.polynomial)-len(other.polynomial),-1,-1):quot[i]=rema[i+len(other.polynomial)-1]*inve%self.modfor j in range(len(other.polynomial)):rema[i+j]-=quot[i]*other.polynomial[j]rema[i+j]%=self.modelse:inve=1/other.polynomial[-1]for i in range(len(self.polynomial)-len(other.polynomial),-1,-1):quot[i]=rema[i+len(other.polynomial)-1]*invefor j in range(len(other.polynomial)):rema[i+j]-=quot[i]*other.polynomial[j]quot=Polynomial(quot,max_degree=self.max_degree,eps=self.eps,mod=self.mod)return quotdef __mod__(self,other):assert type(other)==Polynomialquot=[0]*(len(self.polynomial)-len(other.polynomial)+1)rema=[x for x in self.polynomial]if self.mod:inve=MOD(self.mod).Pow(other.polynomial[-1],-1)for i in range(len(self.polynomial)-len(other.polynomial),-1,-1):quot[i]=rema[i+len(other.polynomial)-1]*inve%self.modfor j in range(len(other.polynomial)):rema[i+j]-=quot[i]*other.polynomial[j]rema[i+j]%=self.modrema.pop()else:inve=1/other.polynomial[-1]for i in range(len(self.polynomial)-len(other.polynomial),-1,-1):quot[i]=rema[i+len(other.polynomial)-1]*invefor j in range(len(other.polynomial)):rema[i+j]-=quot[i]*other.polynomial[j]rema.pop()rema=Polynomial(rema,max_degree=self.max_degree,eps=self.eps,mod=self.mod)return remadef __divmod__(self,other):assert type(other)==Polynomialquot=[0]*(len(self.polynomial)-len(other.polynomial)+1)rema=[x for x in self.polynomial]if self.mod:inve=MOD(self.mod).Pow(other.polynomial[-1],-1)for i in range(len(self.polynomial)-len(other.polynomial),-1,-1):quot[i]=rema[i+len(other.polynomial)-1]*inve%self.modfor j in range(len(other.polynomial)):rema[i+j]-=quot[i]*other.polynomial[j]rema[i+j]%=self.modrema.pop()else:inve=1/other.polynomial[-1]for i in range(len(self.polynomial)-len(other.polynomial),-1,-1):quot[i]=rema[i+len(other.polynomial)-1]*invefor j in range(len(other.polynomial)):rema[i+j]-=quot[i]*other.polynomial[j]rema.pop()quot=Polynomial(quot,max_degree=self.max_degree,eps=self.eps,mod=self.mod)rema=Polynomial(rema,max_degree=self.max_degree,eps=self.eps,mod=self.mod)return quot,remadef __neg__(self):if self.mod:nega=Polynomial([(-x)%self.mod for x in self.polynomial],max_degree=self.max_degree,eps=self.eps,mod=self.mod)else:nega=Polynomial([-x for x in self.polynomial],max_degree=self.max_degree,eps=self.eps,mod=self.mod)return negadef __pos__(self):posi=Polynomial([x for x in self.polynomial],max_degree=self.max_degree,eps=self.eps,mod=self.mod)return posidef __bool__(self):return self.polynomialdef __getitem__(self,n):if n<=len(self.polynomial)-1:return self.polynomial[n]else:return 0def __setitem__(self,n,x):if self.mod:x%=self.modif self.max_degree==-1 or n<=self.max_degree:if n<=len(self.polynomial)-1:self.polynomial[n]=xelif self.eps<abs(x):self.polynomial+=[0]*(n-len(self.polynomial))+[x]def __call__(self,x):retu=0pow_x=1for i in range(len(self.polynomial)):retu+=pow_x*self.polynomial[i]pow_x*=xif self.mod:retu%=self.modpow_x%=self.modreturn retudef __str__(self):return "["+", ".join(map(str,self.polynomial))+"]"def Bostan_Mori(poly_deno,poly_nume,N,mod=0,fft=False,ntt=False):if type(poly_deno)==Polynomial:poly_deno=poly_deno.polynomialif type(poly_nume)==Polynomial:poly_nume=poly_nume.polynomialif ntt:convolve=NTTelif fft:convolve=FFTelse:def convolve(poly_deno,poly_nume):conv=[0]*(len(poly_deno)+len(poly_nume)-1)for i in range(len(poly_deno)):for j in range(len(poly_nume)):conv[i+j]+=poly_deno[i]*poly_nume[j]if mod:for i in range(len(conv)):conv[i]%=modreturn convwhile N:poly_nume_=[-x if i%2 else x for i,x in enumerate(poly_nume)]if N%2:poly_deno=convolve(poly_deno,poly_nume_)[1::2]else:poly_deno=convolve(poly_deno,poly_nume_)[::2]poly_nume=convolve(poly_nume,poly_nume_)[::2]if fft and mod:for i in range(len(poly_deno)):poly_deno[i]%=modfor i in range(len(poly_nume)):poly_nume[i]%=modN//=2return poly_deno[0]mod=10**9+9P=Polynomial([1],max_degree=3000-1,mod=mod)for money in (1,5,10,50,100,500):lst=[0]*(money+1)lst[0]=1lst[money]=-1P/=Polynomial(lst)LI={r:Lagrange_Interpolation(Y=[P[i] for i in range(r,3000,500)],x0=r,xd=500,mod=mod) for r in range(500)}T=int(readline())for _ in range(T):M=int(readline())r=M%500ans=LI[r][M]print(ans)