有 T 组数据,每组数据给出 n 和长度为 n的数列 a[i],判断有没有两个数不互质,如果有输出 "YES",没有输出 "NO"
n≤2e5 1≤a[i]≤1e9
难度:*1600 (普及+/提高)
我们现设MAX=1e9
看到这种题目一定先要看a的数据范围,因为一定跟质数有关,还有与 √MAX 有关
那么a[i]是有两种可能 合数,质数
接下来是常见套路 我们先 筛选出 2~√MAX 之间的质数,大约是 3000 多个
对于a[i],我们先用2~√MAX 之间的质数除 ,如果删后的 a[i] 不为1,那么除后的 a[i] 它一定是个大于 √MAX的质数,∈(√MAX,MAX)
显然对于此时的大质数,我们用mp来存储。
对于2~√MAX 之间的质数 我们完全由能力定义数组来判断它出现的次数,这就用 bool vis1[N]来表示
对于√MAX~MAX 之间的质数,我们用mp来存这种大指数,这就用 map<int,bool> vis2[N]来表示
那么此题就做好了
复杂度为O( 筛选质数+N*prime.size() ) 6e8感觉挺极限的,跑起来900ms
#include<bits/stdc++.h> using namespace std; #define ll long long #define mp make_pair #define pb push_back //vector函数 #define popb pop_back //vector函数 #define fi first #define se second const int N=4e5; //const int M=; //const int inf=0x3f3f3f3f; //一般为int赋最大值,不用于memset中 //const ll INF=0x3ffffffffffff; //一般为ll赋最大值,不用于memset中 int T,n,a[N]; bool vis[N],vis1[N]; vector<int> prime,v; map<int,bool> vis2; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } void getprime() { int M=(int)sqrt(1e9); // printf("%d\n",M); for(int i=2;i<=M;i++) { if(vis[i]) continue; prime.pb(i); for(int j=i;i*j<=M;j++) vis[i*j]=1; } printf("%d",prime.size()); } int main() { // freopen("","r",stdin); // freopen("","w",stdout); T=read(); getprime(); while(T--) { n=read(); bool ok=0; for(int i=1;i<=n;i++) { a[i]=read(); for(int x:prime) { if(x>a[i]) break; if(a[i]%x==0) { if(vis1[x]) ok=1; if(!vis[x]) vis1[x]=1,v.pb(x); while(a[i]%x==0) a[i]/=x; } } if(a[i]!=1) { if(vis2[a[i]]) ok=1; vis2[a[i]]=1; } } if(ok) puts("YES"); else puts("NO"); vis2.clear(); for(int x:v) vis1[x]=0; v.clear(); } return 0; }
标签:vis2,ch,CF1771C,int,1600,质数,MAX,define From: https://www.cnblogs.com/Willette/p/17051034.html