n个数中所有任意两个数的lcm的gcd(数论)
在遥远的公元前65536世纪,β星座的焃碁星人发现了地球,他们对于该星球上碳基生物的大脑构造感到非常的好奇, 在植入了夸克级别的神经元控制器后, 他们夺取了所有生物大脑内惊人的算力,进而控制了所有的生物。
几亿年以后, 人类凭借着自己贫瘠的算力, 造出了庞大而惊人的超大规模集成电路,他们训练的AlphaPenguin 系统经过了几亿亿的和棋训练, 已经达到了与焃碁星人相同的智力水准。
AlphaPenguin在企图破译焃碁星人的最高权限密码,夺回所有生物的算力控制权时, 发现焃碁星人采用了以下的动态加密方式:
比起焃碁星人,AlphaPenguin由于没有足够的算力而对此感到无能为力。因此它采用了分布式计算的方法,将一小部分任务交给了你做。
具体地,你现在得到了n个数, 你需要求出这n个数中所有任意两个数的最小公倍数的最大公因数, 并把答案返回给AlphaPenguin。
几亿年以后, 人类凭借着自己贫瘠的算力, 造出了庞大而惊人的超大规模集成电路,他们训练的AlphaPenguin 系统经过了几亿亿的和棋训练, 已经达到了与焃碁星人相同的智力水准。
AlphaPenguin在企图破译焃碁星人的最高权限密码,夺回所有生物的算力控制权时, 发现焃碁星人采用了以下的动态加密方式:

具体地,你现在得到了n个数, 你需要求出这n个数中所有任意两个数的最小公倍数的最大公因数, 并把答案返回给AlphaPenguin。
输入
第一行一个整数n,表示你得到的数的个数。
第二行n个整数,a1,a2,...,an表示每个数的大小。
第二行n个整数,a1,a2,...,an表示每个数的大小。
输出
一行,一个整数,表示你计算出的结果。
样例输入 Copy
【样例1】
4
10 24 40 80
【样例2】
10
540 648 810 648 720 540 594 864 972 648
样例输出 Copy
【样例1】
40
【样例2】
54
提示
样例解释
在第一个样例中,lcm(10,24)=120,lcm(10,40)=40,lcm(10,80)=80,lcm(24,40)=120,lcm(24,80)=240,lcm(40,80)=80,gcd(120,40,80,120,240,80)=40,因此答案即为40。

在第一个样例中,lcm(10,24)=120,lcm(10,40)=40,lcm(10,80)=80,lcm(24,40)=120,lcm(24,80)=240,lcm(40,80)=80,gcd(120,40,80,120,240,80)=40,因此答案即为40。

这个题一开始没有想出来,看看这位巨巨的博客把:传送门
这个题的题意很简单,就是求n个数的任意两个数的最小公倍数的最大公因数,就是这样。
假设有两个数a,b。
a=p1^a1*p2^a2---------*pn^an,
b=p1^b2*p2^b2---------*pn^bn.
就是这样。
那么
gcd(a,b)=p1^min(a1,b1)*p2^min(a2,b2)-------pn^min(an,bn)
lcm(a,b)=p1^max(a1,b1)*p2^max(a2,b2)-------pn^max(an,bn)
在这里先将求完lcm,再求gcd的结果记为x
看样例{
4
10 24 40 80
10 == 2 ^ 1 +3 ^ 0+5 ^ 1
24 == 2 ^ 3 +3 ^ 1+5 ^ 0
40 == 2 ^ 3 +3 ^ 0+5 ^ 1
80 == 2 ^ 4 +3 ^ 0+5 ^ 1
①对于2的次方数中,对答案x的贡献一定是次小的那个次方数(2^3)
②对于3的次方数中,对答案x不会产生贡献(因为只有一个数有三的次幂)
③对于5的次方数中,对答案x的贡献是因子中有5且次方数最小的那个(5^1)
答案x == ①2 ^ 3 * ③5 ^ 1 == 40
所以我们可以看到,将这n个数唯一分解之后,有这个数的幂次的数量为 >= n - 1才可以
数量 == n的时候,贡献是次小的幂次
数量 == n - 1的时候,贡献是最小的那个幂次
这个时候对每一个质因子的次方数维护在对应的优先队列(小根堆)里面就好啦
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include<queue> using namespace std; typedef long long ll; const int maxn=3e5+100; int tot=0; int biaoji[maxn]; int a[maxn]; int prime[maxn]; int b[maxn]; int cnt[maxn]; vector<int>v[maxn]; int p=0; ll qpow(ll a,ll b){ ll ans=1; while(b){ if(b&1){ ans=(ans*a); } a=(a*a); b/=2; } return ans; } void inint(){ for(int i=2;i<maxn;i++){ if(!biaoji[i]) prime[++tot]=i; for(int j=1;j<=tot&&i*prime[j]<maxn;j++){ biaoji[i*prime[j]]=1; if(i%prime[j]==0){ break; } } } } void get(int x){ p=0; for(int i=1;i<=tot&&prime[i]*prime[i]<=x;i++){ if(x%prime[i]==0){ b[++p]=prime[i]; cnt[p]=0; while(x%prime[i]==0){ x/=prime[i]; cnt[p]++; } } } if(x>1){ b[++p]=x; cnt[p]=1; } } priority_queue <int, vector<int>, greater<int> > q[maxn]; int main(){ inint(); int n; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; get(a[i]); for(int j=1;j<=p;j++){ q[b[j]].push(cnt[j]); } } ll ans=1ll; for(int i=0;i<maxn;i++){ if(q[i].size()==n-1){ ans*=qpow(i,q[i].top()); } else if(q[i].size()==n){ q[i].pop(); ans*=qpow(i,q[i].top()); } } cout<<ans<<endl; return 0; }

浙公网安备 33010602011771号