显然对于 n≤103 且 ai≤109 的情况,直接乘起来会达到 109×103 的量级,即使使用 python,存储也是一个很难的问题。
不妨考虑 gcd 函数的本质。
我们假设 a=p1q1p2q2p3q3⋯pgqg,b=p1r1p2r2p3r3⋯pgrg,其中 p 为质数,g 为 109 内质数的数量,qi∈[0,logpi(109)],ri∈[0,logpi(109)]。
根据唯一分解定理,每一个数都有这样的唯一一个分解。
那么 gcd(a,b)=p1min(q1,r1)p2min(q2,r2)⋯pgmin(qg,rg),ab=p1q1+r1p2q2+r2⋯pgqg+rg。
于是我们可以把 a 序列中的 n 个数全部分解质因数,然后 i=1∏nai=p1j=1∑nq1p2j=1∑nq2⋯pgj=1∑nqg。
b 序列同理。
于是 gcd(i=1∏nai,i=1∏mbi) 就可以通过上面提到的式子 gcd(a,b)=p1min(q1,r1)p2min(q2,r2)⋯pgmin(qg,rg),ab=p1q1+r1p2q2+r2⋯pgqg+rg 推出。
推出后得到式子:
gcd(i=1∏nai,i=1∏mbi)=p1min(j=1∑nq1,j=1∑mr1)p2min(j=1∑nq2,j=1∑mr2)⋯pgmin(j=1∑nqg,j=1∑mrg)。
具体实现起来,我们可以使用 map 统计。
但是如果对于 ai=998244353,我们显然不能从 1 枚举到 998244353。
引出一个性质:任意一个整数 a 至多有 1 个大于 a 的质因数。
证明:如果有两个大于 a 的质因数,它们的乘积一定比 a 大。
所以我们可以枚举到 109(大概是 31623,代码中为了保险我取了 105)。如果有比 31623 大的质因数,我们把它单独保存到一个数组中,这样我们只需要枚举最多 n 个需要被处理的大于 31623 的质因数。
时间复杂度是 O(nlog10n) 的,瓶颈在于分解质因数。
#include<bits/stdc++.h>
using namespace std;
map<int,int>mp1,mp2;
int n,m;
const int mod=1000000000;
int a[1005],b[1005];
int chu[2005],cnt;
long long ans;
long long qpow(long long a,int b){
long long res=1;
while(b){
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res%mod;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
long long x=a[i];
for(int j=2;j*j<=a[i];j++){
while(x%j==0){
mp1[j]++;
x/=j;
}
}
if(x!=1){
mp1[x]++;
chu[++cnt]=x;
}
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d",&b[i]);
long long x=b[i];
for(int j=2;j*j<=b[i];j++){
while(x%j==0){
mp2[j]++;
x/=j;
}
}
if(x!=1){
mp2[x]++;
chu[++cnt]=b[i];
}
}
ans=1;
bool flag=1;
sort(chu+1,chu+cnt+1);
for(int i=1;i<=100000;i++){
if(mp1[i]<mp2[i])ans=ans*qpow(i,mp1[i]);
else ans=ans*qpow(i,mp2[i]);
if(ans>mod)flag=0;
ans%=mod;
}
for(int i=1;i<=cnt;i++){
int x=chu[i];
if(x<=100000)continue;
ans=ans*qpow(x,min(mp1[x],mp2[x]));
if(ans>mod)flag=0;
ans%=mod;
}
if(flag)cout<<ans%mod;
else printf("%09lld",ans);
return 0;
}