洛谷——P1621 集合
阿新 • • 發佈:2017-10-16
logs print bool 多少 pan 屬於 str tchar pri
P1621 集合
題目描述
現在給你一些連續的整數,它們是從A到B的整數。一開始每個整數都屬於各自的集合,然後你需要進行一下的操作:
每次選擇兩個屬於不同集合的整數,如果這兩個整數擁有大於等於P的公共質因數,那麽把它們所在的集合合並。
反復如上操作,直到沒有可以合並的集合為止。
現在Caima想知道,最後有多少個集合。
輸入輸出格式
輸入格式:
一行,三個整數A,B,P。
【數據規模】
A≤B≤100000;
2≤P≤B。
輸出格式:
一個數,表示最終集合的個數。
輸入輸出樣例
輸入樣例#1:10 20 3輸出樣例#1:
7
說明
有80%的數據B≤1000。
樣例解釋{10,20,12,15,18},{13},{14},{16},{17},{19},{11}。
歐拉篩+並查集
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define N 100002 using namespace std; bool not_prime[N],vis[N]; int A,B,p,fx,tot,ans,fa[N],prime[N]; 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*10+ch-‘0‘,ch=getchar(); return x*f; } int Euler_sieve() { for(int i=2;i<=B;i++) { if(!not_prime[i]) prime[++tot]=i; for(intj=1;j<=tot;j++) { if(i*prime[j]>B) break; not_prime[i*prime[j]]=1; if(i%prime[j]==0) break; } } } int find(int x) { if(fa[x]==x) return x; fa[x]=find(fa[x]); return fa[x]; } int main() { A=read(),B=read(),p=read(); Euler_sieve(); for(int i=1;i<=B;i++) fa[i]=i; for(int i=p;i<=B;i++) if(!not_prime[i]) { fx=find(i); for(int j=2;j<=B;j++) { if(i*j>B) break; if(i*j<A) continue; fa[find(i*j)]=fx; } } for(int i=A;i<=B;i++) if(!vis[find(i)]) ans++,vis[find(i)]=true; printf("%d",ans); return 0; }
洛谷——P1621 集合