上一次打是4月20几号,期间鸽了好多场,加上期间也渐渐松懈了,没怎么做题,昨晚这场状态直接爆炸
这道题我现在知道两种做法,最好想的感觉就是分解质因数了,比赛时候不知为啥没想到这个点,等到快结束了才反应过来。
将每个数的质因数分解出来,其中质因数被包含n-1次及以上才能对最后的gcd产生贡献,贡献为该质因数倒数第二小的指数大小。
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll prime[200005],p[800005],cnt,sum[200005];
ll a[200005];
ll c[200005],d[200005][5];
void euler(int n)
{
for(int i=2;i<=n;i++)
{
if(!p[i])
{
prime[++cnt]=i;sum[i]=1;}
for(int j=1;j<=cnt;j++)
{
if(i*prime[j]>n)
{
break;}
p[prime[j]*i]=1;
if(i%prime[j]==0)
{
break;}
}
}
for(int i=1;i<=200002;i++)
{
d[i][1]=99999999;d[i][2]=99999999;}
}
ll apow(ll a,ll b)
{
ll s=1;while(b){
if(b&1){
s=s*a;}a=a*a;b>>=1;}return s;}
int main()
{
ll t,n,m,flag=0,j,op;
euler(200000);
scanf("%lld",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);}
if(n==2)
{
printf("%lld\n",(a[1]*a[2])/__gcd(a[1],a[2]));return 0;}
for(int i=1;i<=n;i++)
{
m=a[i];j=1;
if(sum[m]==1)
{
c[m]++;
if(1<=d[m][1])
{
d[m][2]=d[m][1];d[m][1]=1;}
else
{
if(1<=d[m][2])
{
d[m][2]=1;}
}
continue;
}
while(m>1)
{
op=0;
if(m%prime[j]==0)
{
c[prime[j]]++;
while(m%prime[j]==0)
{
m/=prime[j];
op++;}
if(op<=d[prime[j]][1])
{
d[prime[j]][2]=d[prime[j]][1];
d[prime[j]][1]=op;
}
else
{
if(op<d[prime[j]][2])
{
d[prime[j]][2]=op;}
}
j++;
}
else
{
j++;}
}
}
ll ans=1;
for(int i=1;i<=cnt;i++)
{
if(c[prime[i]]==n-1)
{
ans*=apow(prime[i],d[prime[i]][1]);}
if(c[prime[i]]==n)
{
ans*=apow(prime[i],d[prime[i]][2]);}
}
printf("%lld\n",ans);
return 0;
}