Empire Strikes Back
题意:
给定$K$个数字,求最小的正整数$n$,使得$\prod_{i=1}^{K}{a_i !} | n!$
解法:
注意到$$\sum_{p为质数}{1/p} = O(loglogn)$$,
这样考虑用筛法筛出来$\prod_{i=1}^{K}{a_i !}$的各个质因数个数(实现时记一下大于每个数字的有多少个$a_i$)
这样只要对于每一个质数求出最小的$tmp$,使得${p_i}^{cnt(i)} | tmp!$
考虑二分,而后求$mid!$内有多少个$p$,可以用容斥或者直接$[mid/p]+[[mid/p]/p] + ...$。
总效率$O(nlognlogn+x(n)*logn)$
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 #define N 10000010 6 #define LL long long 7 #define INF 0x3f3f3f3f3f3f3f3fLL 8 9 using namespace std; 10 11 int n,tot; 12 int a[1000010]; 13 int num[N],prime[N],S[N]; 14 LL cnt[N]; 15 bool v[N]; 16 17 LL check(LL x,LL n) 18 { 19 LL ans=0; 20 for(;n>1;n/=x) ans+=n/x; 21 return ans; 22 } 23 24 LL calc(int x,LL n) 25 { 26 if(!n) return 0LL; 27 if(n==1) return (LL)x; 28 LL l=1,r=INF; 29 while(r-l>2) 30 { 31 LL mid=(l+r)>>1; 32 if(check(x,mid)>=n) r=mid; 33 else l=mid; 34 } 35 for(LL i=l;i<=r;i++) 36 if(check(x,i)>=n) return i; 37 return -1; 38 } 39 40 int main() 41 { 42 scanf("%d",&n); 43 for(int i=1;i<=n;i++) scanf("%d",&a[i]),S[a[i]]++; 44 for(int i=N-2;i>=1;i--) S[i]+=S[i+1]; 45 for(int i=1;i<N;i++) num[i]=i; 46 for(int i=2;i<N;i++) 47 { 48 if(v[i]) continue; 49 prime[++tot]=i; 50 for(int j=i;j<N;j+=i) 51 { 52 v[j]=1; 53 while(num[j]%i==0) 54 { 55 num[j]/=i; 56 cnt[tot]+=(LL)S[j]; 57 } 58 } 59 } 60 LL ans=1; 61 for(int i=1;i<=tot;i++) 62 ans = max(ans, calc(prime[i],cnt[i])); 63 cout << ans << endl; 64 return 0; 65 }