彼らは爆発します
T1の レンガ
シミュレーション
T2のデジタル
高齢者右辺値問題の詳細な解決策をありがとう
問題は、つまり、N- $スタート0出力から、その最初の非低い!$ 10は、すなわちすべてのExt $要因(接尾辞0削除)削除される(10、N-!)$
およびK == 1 $内線(10、N!)\%10 $、K == 2 $内線(10、N!)\%100 $、k個の== 3における出力の数......
10、例えば
$ \%$ 10は、第1の$ \%2 $をと回答の$ \ $ 5%、CRTの需要との最終的な答えを見つけることができます
$内線(10、n個!)\%2 $少し特別審査員(通常は0、しかし、あなたは暴力を実行することができますので、小さな小さなではないかもしれません)
あなたはそれが必要式を変更する必要が5 $ $内線(10、n個!)\%
$$ \開始{アレイ} {RL}拡張(10、N!)&= \ FRAC {N!} {10 ^ {FP(10、N!)}} &= \ FRAC {N!} {2 ^ { FP(10、N!)} 5 ^ {FP(10、N!))}} &= \ FRAC {N!} {2 ^ {FP(5、N!)} 5 ^ {FP(5、N! )}} &= \ FRAC {拡張(5、N!))} {2 ^ {FP(5、N!)}} \端{アレイ} $$
$ FP(5、nは!)$時間$ log_5 ^ n個の$に決定することができ、次いで、$ 2 ^ {FP(5は、N!)}は、わずか$拡張(5を残し、そこ逆元を$ N !)$
$拡張(k、n)は、自然の$拡張(AB、N)=拡張(N)*内線(B、N)(、bは素数である)$を$
所以$$ \ {アレイ} {RL}拡張(5、N!)&= \ PRODの\のlimits_ {k = 1} ^ {n}は拡張(5、K)\\始める&= \ PRODの\のlimits_ {Kを\ [1、n]は、5 | [1、N]におけるk}拡張(5、K)\回\ PROD \ limits_ {k個の\、5 \ NMID K}拡張(5、K)\\ &=内線( 5、(\ FRAC {N} {5})!)\回\拡張(5、K)\\ PROD \ limits_ {[1、n]は、5 \ NMID KのK \} &=拡張(5、( \ FRAC {N} {5})!)\回\ PROD \ limits_ {[1、N]のK \、5 \ NMID K}のk \端{アレイ} $$
と
時間(\ PRODの\のlimits_ {[1,5]内のk \、5 \ NMID K} K \ $$拡張(5、N!)=拡張(5、(\ FRAC {N} {5})!)所以)^ {\ lfloorの\のFRAC {N} {5} \ rfloor} \回\ PROD \ {limits_のK \ [1、N \%5]、5 \ NMID K} K(MOD 5)$$
$ 2 ^ {FP(5、n個!)} $を求め、最終的な$内線(5、n個!)$フロントを掛けるとは、このように$内線(10、n個!)\%5 $を得逆元です見つけます
そして、$内線(10、N!)2 $は、CRTが(大神はない、本当にCRTを行う)10 $の$内線(10、n個!)\%溶液を得た走った\%
K == 2及びK == 3と同様
そして、== 3ケーススタディをkに
(K {NMID K \ [1125]のK \、5} \ PRODの\のlimits_)倍\ $$拡張(5、N!)=拡張(5、(\ FRAC {N} {5})!)^ { \ lfloorの\のFRAC {n}が{125}で\ rfloor} \回\ PROD \ limits_ {k個の\ [1、N \%125]、5 \ NMID K} K(MOD 125)$$
最後ボー富里(コード)
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int T,k,a[110],FP[110],b[110],fac[150]; long long ans[11000]; int c[5],p[5],phi; inline void read(){ register char r; while(r=getchar(),r<'0'||r>'9'); a[0]=0; a[++a[0]]=r^48; while(r=getchar(),r>='0'&&r<='9') a[++a[0]]=r^48; } long long qpow(long long a,long long b,long long mod){ long long ans=1; while(b){ if(b&1) ans=ans*a%mod; b>>=1; a=a*a%mod; } return ans; } int div(int a[],int b){ int tmp=0; for(register int i=a[0];i;i--){ tmp=tmp*10+a[i]; a[i]=tmp/b,tmp%=b; } while(a[a[0]]==0&&a[0]>=1) a[0]--; return tmp; } void jia(int a[],int b[]){ int tmp=0; for(register int i=1;i<=max(a[0],b[0]);i++){ tmp=a[i]+b[i]+tmp; b[i]=tmp%10; tmp/=10; } b[0]=max(a[0],b[0]); while(tmp) b[++b[0]]=tmp%10,tmp/=10; } int MOD(int a[],int mod){ return div(a,mod); } int work_FP(){ memset(FP,0,sizeof(FP)); memcpy(b,a,sizeof(b)); while(b[0]){ div(b,5); jia(b,FP); } return MOD(FP,phi); } void work_to_2(){ if(k==1) p[1]=2,p[2]=5,phi=4; else if(k==2) p[1]=4,p[2]=25,phi=20; else if(k==3) p[1]=8,p[2]=125,phi=100; if(a[0]>1) c[1]=0; else{ c[1]=1; for(register int i=1;i<=a[1];i++) c[1]=c[1]*i%p[1]; } } void work_to_5(){ int w=work_FP()+phi; w=qpow(qpow(2,w,p[2]),phi-1,p[2]); fac[0]=1; for(register int i=1;i<=p[2];i++){ fac[i]=fac[i-1]; if(i%5!=0) fac[i]=fac[i]*i%p[2]; } c[2]=1; while(a[0]){ memcpy(b,a,sizeof(b)); memset(FP,0,sizeof(FP)); div(a,5); c[2]=c[2]*fac[div(b,p[2])]%p[2]; jia(b,FP); c[2]=c[2]*qpow(fac[p[2]],MOD(FP,phi),p[2])%p[2]; } c[2]=c[2]*w%p[2]; } void work(){ for(register int i=a[0];i>=1;i--) b[++b[0]]=a[i]; memcpy(a,b,sizeof(a)); work_to_2(); work_to_5(); } void exgcd(int a,int b,int &x,int &y){ if(!b){ x=1; y=0; return; } exgcd(b,a%b,x,y); int t=y; y=x-a/b*y; x=t; return; } int CRT(){ int sum=p[1]*p[2]; int ans=0; for(register int i=1;i<=2;i++){ int a=sum/p[i],x,y; exgcd(a,p[i],x,y); ans=(ans+a*x*c[i]%sum)%sum; } return (ans%sum+sum)%sum; } void out(int x){ if(k==1) printf("%d\n",x%10); if(k==2) printf("%d%d\n",(x/10)%10,x%10); if(k==3) printf("%d%d%d\n",(x/100)%10,(x/10)%10,x%10); } int main(){ //freopen("3.out","w",stdout); scanf("%d",&T); ans[0]=1; for(register int i=1;i<=10000;i++){ ans[i]=ans[i-1]*i; while(ans[i]%10==0) ans[i]/=10; ans[i]%=((int)1e8); } while(T--){ read(); scanf("%d",&k); if(a[0]<=4){ int n=0; for(register int i=1;i<=a[0];i++) n=n*10+a[i]; out(ans[n]); } else{ work(); out(CRT()); } } }
T3 甜圈
要求完成的任务必须按顺序而且只能做一次,用hash表示状态
将甜圈编号作为线段树下标,经典的线段树操作就可以了