AtCoder Beginner Contest 177 比赛人数9636
AtCoder Beginner Contest 177 E Coprime 线性筛素数+统计质因数数量+特判
总目录详见https://blog.csdn.net/mrcrack/article/details/104454762
在线测评地址https://atcoder.jp/contests/abc177/tasks/abc177_e
题目大意:给定一个数组,若其中任意两个元素,两两互质,输出pairwise coprime,若做不到两两互质,但能做到所有元素最大公约数是1,输出setwise coprime, 若所有元素最大公约数不是1,输出not coprime。
基本思路:请看样例模拟过程:
3
3 4 5
pairwise coprime
3=3,4=2^2(2^2,算2在4中出现1次),5=5
质因数出现1次的有3,2,5
3
6 10 15
setwise coprime
6=2*3,10=2*5,15=3*5
质因数出现2次的有2,3,5
3
6 10 16
not coprime
6=2*3,10=2*5,16=2^4(2^4,算2在16中出现1次)
质因数出现1次的有3,5
质因数出现3次的有2
若自觉的算法没有问题,但代码一直无法AC,那么,该题需特判的例子提供给大家
Input:
5
4 9 25 49 121
Output:
pairwise coprime
Input:
5
1 1 1 1 1
Output:
pairwise coprime
AC代码如下:
#include <cstdio>
#include <algorithm>
#define maxn 1000010
using namespace std;
int a[maxn],prime[maxn],not_prime[maxn],tot,vis[maxn];
void linear_shaker(int x){//线性筛素数
int i,j;
for(i=2;i<=x;i++){
if(!not_prime[i])prime[++tot]=i;//prime[i]=j表示第i个质数是j
for(j=1;prime[j]*i<=x;j++){
not_prime[i*prime[j]]=prime[j];//此处用了技巧,记录了合数i*prime[j]的最小质因数prime[j]
if(i%prime[j]==0)break;
}
}
}
int main(){
int n,i,m=0,b,c,cnt=0;//cnt统计质因数最大出现次数
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d",&a[i]),m=max(m,a[i]);//m找出最大a[i]值,减轻线性筛素数的运算量。
linear_shaker(m);
for(i=1;i<=n;i++){
b=a[i];
while(not_prime[b]){
c=not_prime[b];
vis[c]++,cnt=max(cnt,vis[c]);//vis[c]统计质因数c出现次数
while(b%c==0)b/=c;//处理2^4这种形式
}
if(b!=1)vis[b]++,cnt=max(cnt,vis[b]);//注意此处条件if(b!=1),若没有此句,该题要不断的WA
}
if(cnt<=1)printf("pairwise coprime\n");//注意此处条件if(cnt<=1),若没有此句,该题要不断的WA,若数组中元素全是1,cnt==0
else if(cnt<n)printf("setwise coprime\n");
else printf("not coprime\n");//cnt>=n
return 0;
}