P1621 集合 題解並查集,篩素數
阿新 • • 發佈:2022-03-06
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cstdlib> #include<cmath> #define maxn 100010 using namespace std; int f[maxn]; int a,b,p,ans; bool prime[maxn]; int vis[maxn]; int cnt; int getf(int x) { if(f[x]==0) return x;//注意這裡的條件與返回值 else { f[x]=getf(f[x]);//路徑壓縮 return f[x]; } } void merge(int x,int y) { int t1=getf(x),t2=getf(y); if(t1!=t2) { f[t2]=t1; } } int make_prime() //普通篩 { memset(prime,1,sizeof(prime)); int k=sqrt(b); prime[0]=prime[1]=0; for(int i=2;i<=k;i++) if(prime[i]) for(int j=2*i;j<maxn;j+=i) prime[j]=0; } int main() { cin>>a>>b>>p; for(int i=a;i<=b;i++) f[i]=0;//為了方便統計集合的個數,每個代表根指向0 make_prime(); for(int i=p;i<=b;i++) //找出p~b之間的素數 if(prime[i]) vis[++cnt]=i; //記錄 for(int i=1;i<=cnt;i++) //找出a~b之間符合條件的數,合併 { int cc=0; while(cc*vis[i]<a) cc++; //確保是a~b之間的,不要超範圍,不然後面沒法統計 while(vis[i]*(cc+1)<=b) { merge(vis[i]*cc,vis[i]*(cc+1)); //合併 cc++; } } for(int i=a;i<=b;i++) if(f[i]==0) ans++; //統計個數 cout<<ans<<endl; return 0; }