阶乘 / factorial
【问题描述】
有n个正整数a[i],设它们乘积为p,你可以给p乘上一个正整数q,使p*q刚好为正整数m的阶乘,求m的最小值。
【输入】
共两行。
第一行一个正整数n。
第二行n个正整数a[i]。
【输出】
共一行
一个正整数m。
【输入输出样例1】
1 6 |
3
|
对于10%的数据,n<=10
对于30%的数据,n<=1000
对于100%的数据,n<=100000,a[i]<=100000
才学会线性筛……
补充——2018-10-14
解释一下代码中的 count函数:【阶乘分解】
N!中的质因子p的个数就等于1~N中每个数包含质因数p的个数之和,那么至少包含一个质因子p的显然有 N/p 个.
同理,p2 的倍数,即至少包含两个质因子 p 的有 N/p2 个。不过其中一个已经在N/p中算过了,所以只需要统计第 2 个质因子,即累加上 N/p2.
综上,N!中质因子 p 的个数为:
N/p + N/p2 +N/p3 …… + N/plogpN
code
#include<stdio.h> #include<algorithm> #define ll long long using namespace std; const int MX=100001; bool bz[MX]; int n,tot; int fr[MX],pri[MX],cnt[MX],a[MX][2]; void pre() { for(int i=2;i<=MX;++i) { if(!bz[i]) pri[++pri[0]]=i,fr[i]=i; for(int j=1;j<=pri[0];++j) { if(i*pri[j]>MX) break; bz[i*pri[j]]=1; fr[i*pri[j]]=pri[j]; if(i%pri[j]==0) break; } } } int count(int x,int y) { int re=0; while(x>=y) { re+=x/y; x/=y; } return re; } bool jud(int x){ for(int i=1;i<=tot;++i) { if( count(x,a[i][0]) < a[i][1] ) return 0; } return 1; } void pread() { int x; scanf("%d",&x); while(x!=1) { cnt[fr[x]]++; x/=fr[x]; } } int main() { // freopen("factorial.in","r",stdin),freopen("factorial.out","w",stdout); pre(); scanf("%d",&n); while(n--) pread(); for(int i=2;i<=MX;++i) if(cnt[i]) { a[++tot][0]=i; a[tot][1]=cnt[i]; } if(tot==0) { printf("1"); return 0; } int ans,l=1,r=1e10,mid; while(l<=r) { mid=(l+r)>>1; if(jud(mid)) { ans=mid; r=mid-1; } else l=mid+1; } printf("%d",ans); return 0; }
从0到1很难,但从1到100很容易