[AtCoder] Beginner Contest 177 E - Coprime
Solutions Atcoder 数论 质因数分解
Lastmod: 2020-09-18 周五 19:12:38

E - Coprime

题目大意

给出数组 $A$ 如果其中数字两两互质则返回 “pairwise coprime”,如果整个数组 $gcd$ 为 $1$ 则返回 “setwise coprime”,其他情况返回 “not coprime”

简要题解

显然 setwise 很好判断。

对于 pairwise 可以将每个数分解因数,则任意 $A_{i}$ 不和其他的任何项有相同的质因子,于是统计 $A$ 中所有的质因子频率,之后判断 $A_{i}$ 与其他因子频率的关系即可。

这里数组长度 $n \le 10^6$ 比较大,于是采用挂链分解的方式。

复杂度

$T$:$O(C + nlogC)$ 其中 $C \le 10^6$ 为 $A_{i}$ 的范围

$S$:$O(n)$

代码实现

#include <bits/stdc++.h>
using namespace std;

const int M=1e6+5;
int a[M];

int gcd(int a,int b)
{
	return b?gcd(b,a%b):a;
}

int isp[M],pri[M],pre[M],npri=0;
void get_pri()
{
    for(int i=2;i<M;i++)
    {
        if(!isp[i])
        {
            pre[i]=i;
            pri[npri++]=i;
        }
        for(int j=0;j<npri&&pri[j]*i<M;j++)
        {
            isp[i*pri[j]]=1;
            pre[i*pri[j]]=pri[j];
            if(i%pri[j]==0) break;
        }
    }
}
vector<int> get_factor(int nu)
{
    vector<int> fa;
    if(nu==1) return fa; // fa.push_back(1);
    while(nu!=1)
    {
        fa.push_back(pre[nu]);
        nu/=pre[nu];
    }
    return fa;
}

int cnt[M],cnt2[M];

int main()
{
	get_pri();
	int n; scanf("%d",&n);
	for(int i=0;i<n;i++)
		scanf("%d",&a[i]);

	for(int i=0;i<n;i++)
	{
		vector<int> fas=get_factor(a[i]);
		for(int i:fas)
			cnt[i]++;
	}
	int f=1;
	for(int i=0;i<n;i++)
	{
		vector<int> fas=get_factor(a[i]);
		for(int i:fas)
			cnt2[i]++;
		for(int i:fas)
			if(cnt2[i]<cnt[i])
			{
				// cout<<i<<" "<<cnt[i]<<" "<<cnt2[i]<<endl;
				f=0;
				break;
			}
		if(f==0) break;
		for(int i:fas)
			cnt2[i]--;
	}
	if(f)
	{
		printf("pairwise coprime\n");
		return 0;
	}
	int g=a[0];
	for(int i=1;i<n;i++)
		g=gcd(g,a[i]);
	printf("%s\n",g==1 ? "setwise coprime" : "not coprime");
	return 0;
}
Prev: [AtCoder] Beginner Contest 177
Next: [LeetCode] 1575. Count All Possible Routes