您的位置:首页 > 其它

codeforces 300E Empire Strikes Back 数论+二分查找

2016-07-22 08:27 411 查看
题目链接:http://codeforces.com/problemset/problem/300/E

题意:给定n个数(a1,a2……an),求p,其中p=n!,且p可以被(a1!a2!…….*an!)整除。

分析:将a1!a2!……*an!分解成质因子相乘的形式,但是肯定不可能一个数一个数分解,巧妙的运用从大数转换成小数的思想,求出各个质因子及其个数。再运用二分求解对于每个质因子而言最小的nn,所有的nn取最大即为结果

源代码:

#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<cmath>
#include<stack>
#include<vector>
#include<set>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1000005;
typedef __int64 LL;

LL num[N*10];
int p[N*10];
bool vis[N*10];
int prime
;
int tot=0;
LL sum;
int ma;

void init()
{
memset(vis,false,sizeof vis);
for(int i=2; i<N*10; i++)
{
if(!vis[i])
{
prime[tot++]=i;
p[i]=i;
}
for(int j=0; j<tot&&i<=N*10/prime[j]; j++)
{
vis[i*prime[j]]=true;
p[i*prime[j]]=prime[j];
if(i%prime[j]==0)
break;
}
}
}

void cal()
{
for(int i=ma;i>=2;i--)
{
if(p[i]!=i)
{
num[p[i]]+=num[i];
num[i/p[i]]+=num[i];
}
}
}

bool ok(LL m,int a,LL n)
{
LL res=0;
while(m)
{
res+=m/a;
m/=a;
if(res>=n)
return true;
}
return false;

}

LL BST(int a,LL n)
{
LL l=1,r=sum;
LL ans=-1;
while(l<=r)
{

LL mid=(l+r)/2;
if(ok(mid,a,n))
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
return ans;
}

LL solve()
{
LL ans=1;
for(int i=0;i<tot;i++)
{
if(num[prime[i]])
{
ans=max(ans,BST(prime[i],num[prime[i]]));
}
else break;
}
return ans;
}

int main()
{
int n;
init();
while(~scanf("%d",&n))
{
memset(num,0,sizeof num);
ma=0;
sum=0;
for(int i=0; i<n; i++)
{
int x;
scanf("%d",&x);
ma=max(ma,x);
num[x]++;
sum+=x;
}
for(int i=ma-1;i>=2;i--)
{
num[i]+=num[i+1];
}

cal();

printf("%I64d\n",solve());
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces Empire-Str