【NOIP2018複習】階乘(數論)
阿新 • • 發佈:2018-12-19
1174.階乘
時間限制:1000MS記憶體限制:256000KB
題目描述
有n個正整數a[i],設它們乘積為p,你可以給p乘上一個正整數q,使p*q剛好為正整數m的階乘,求m的最小值。
輸入
共兩行。 第一行一個正整數n。 第二行n個正整數a[i]。
輸出
共一行 一個正整數m。
輸入樣例複製
1 6
輸出樣例複製
3
說明
樣例解釋: 當p=6,q=1時,p*q=3! Data Constraint 對於10%的資料,n<=10 對於30%的資料,n<=1000 對於100%的資料,n<=100000,a[i]<=100000
題解:可以把p分解質因數,假設p=∏ai^bi(ai為質數),那麼只要m!包含了每個ai^bi,m!就包含p。
所以對於每個ai^bi,分別求出滿足條件的最小的m,取最大值即可。
怎麼求m?
先看一個簡單的問題:
27!裡面有多少個3相乘?
27!=1*2*...*27
包含1個3的數有27/(3^1)=9個
包含2個3的數有27/(3^2)=3個
包含3個3的數有27/(3^3)=1個
總共:9+3+1=13個
所以27!裡面有13個3相乘。
用這個方法就可以求得m!有多少個ai相乘,二分判斷即可。
var m,pm,num,l,r,ans,i,n,j:longint; a,t,b,p:array[0..10000000]of longint; f:array[0..10000000]of boolean; procedure sushu(x:longint); var i,j:longint; begin i:=1; f[0]:=false; f[1]:=false; for i:=2 to x do begin if f[i]=true then begin inc(num); p[num]:=i; b[i]:=i; end; for j:=1 to num do begin f[p[j]*i]:=false; b[p[j]*i]:=b[i]; if i mod p[j]=0 then break; if i*p[j+1]>x then break; end; end; end; procedure add(x:longint); begin while x>1 do begin if(b[x]>pm) then pm:=b[x]; inc(t[b[x]]); //writeln(b[x]); x:=x div b[x]; end; end; function check(x:longint):boolean; var i:longint; j,s:int64; begin for i:=1 to pm do begin if f[i]=false then continue; j:=i; s:=0; while(j<=x) do begin s:=s+(x div j); j:=j*i; if s>=t[i] then break; end; if s<t[i] then exit(false); end; exit(true); end; procedure init; begin for i:=1 to n do begin read(a[i]); add(a[i]); end; end; begin //assign(input,'1.in');reset(input); readln(n); fillchar(f,sizeof(f),true); sushu(1000000); init; l:=pm;r:=1000000000; while(l<r) do begin m:=(l+r)div 2; if check(m) then r:=m else l:=m+1; end; writeln(l); //close(input); end.