题解:SP18202 HG - HUGE GCD

显然对于 n103n\le10^3ai109a_i\le10^9 的情况,直接乘起来会达到 109×10310^{9\times 10^3} 的量级,即使使用 python,存储也是一个很难的问题。

不妨考虑 gcd\gcd 函数的本质。

我们假设 a=p1q1p2q2p3q3pgqga=p_1^{q_1}p_2^{q_2}p_3^{q_3}\cdots p_g^{q_g}b=p1r1p2r2p3r3pgrgb=p_1^{r_1}p_2^{r_2}p_3^{r_3}\cdots p_g^{r_g},其中 pp 为质数,gg10910^9 内质数的数量,qi[0,logpi(109)]q_i\in [0,\log_{p_i}(10^9)]ri[0,logpi(109)]r_i\in[0,\log_{p_i}(10^9)]

根据唯一分解定理,每一个数都有这样的唯一一个分解。

那么 gcd(a,b)=p1min(q1,r1)p2min(q2,r2)pgmin(qg,rg)\gcd(a,b)=p_1^{\min(q_1,r_1)}p_2^{\min(q_2,r_2)}\cdots p_g^{\min(q_g,r_g)}ab=p1q1+r1p2q2+r2pgqg+rgab=p_1^{q_1+r_1}p_2^{q_2+r_2}\cdots p_g^{q_g+r_g}

于是我们可以把 aa 序列中的 nn 个数全部分解质因数,然后 i=1nai=p1j=1nq1p2j=1nq2pgj=1nqg\prod \limits_{i=1}^na_i=p_1^{\sum \limits_{j=1}^n q_1}p_2^{\sum \limits_{j=1}^n q_2}\cdots p_g^{\sum \limits_{j=1}^n q_g}

bb 序列同理。

于是 gcd(i=1nai,i=1mbi)\gcd(\prod\limits_{i=1}^n a_i,\prod\limits_{i=1}^m b_i) 就可以通过上面提到的式子 gcd(a,b)=p1min(q1,r1)p2min(q2,r2)pgmin(qg,rg)\gcd(a,b)=p_1^{\min(q_1,r_1)}p_2^{\min(q_2,r_2)}\cdots p_g^{\min(q_g,r_g)}ab=p1q1+r1p2q2+r2pgqg+rgab=p_1^{q_1+r_1}p_2^{q_2+r_2}\cdots p_g^{q_g+r_g} 推出。

推出后得到式子:

gcd(i=1nai,i=1mbi)=p1min(j=1nq1,j=1mr1)p2min(j=1nq2,j=1mr2)pgmin(j=1nqg,j=1mrg)\gcd(\prod\limits_{i=1}^n a_i,\prod\limits_{i=1}^m b_i)=p_1^{\min(\sum \limits_{j=1}^n q_1,\sum \limits_{j=1}^m r_1)}p_2^{\min(\sum \limits_{j=1}^n q_2,\sum \limits_{j=1}^m r_2)}\cdots p_g^{\min(\sum \limits_{j=1}^n q_g,\sum \limits_{j=1}^m r_g)}

具体实现起来,我们可以使用 map 统计。

但是如果对于 ai=998244353a_i=998244353,我们显然不能从 11 枚举到 998244353998244353

引出一个性质:任意一个整数 aa 至多有 11 个大于 a\sqrt{a} 的质因数。

证明:如果有两个大于 a\sqrt{a} 的质因数,它们的乘积一定比 aa 大。

所以我们可以枚举到 109\sqrt{10^9}(大概是 3162331623,代码中为了保险我取了 10510^5)。如果有比 3162331623 大的质因数,我们把它单独保存到一个数组中,这样我们只需要枚举最多 nn 个需要被处理的大于 3162331623 的质因数。

时间复杂度是 O(nlog10n)\operatorname{O}(n\log_{10} n) 的,瓶颈在于分解质因数。

#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;
		}
//		printf("------------------------------\n");
	}
	
	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])cout<<i<<' '<<mp1[i]<<' '<<mp2[i]<<endl;
		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;
}
posted @   Weslie_qwq  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示