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 }
View Code

 

posted @ 2017-03-13 19:03  lawyer'  阅读(136)  评论(0编辑  收藏  举报