p1621 集合(並查集+素數
傳送門題目描述
caima 給你了所有 [a,b] 範圍內的整數。一開始每個整數都屬於各自的集合。每次你需要選擇兩個屬於不同集合的整數,如果這兩個整數擁有大於等於 p 的公共質因數,那麼把它們所在的集合合併。
重複如上操作,直到沒有可以合併的集合為止。
現在 caima 想知道,最後有多少個集合。
輸入格式
一行,共三個整數 a,b,pp,用空格隔開。
輸出格式
乙個數,表示最終集合的個數。
輸入輸出樣例
輸入 #1
10 20 3
輸出 #1
說明/提示
樣例 1 解釋
對於樣例給定的資料,最後有 ,,,,,, 共 7 個集合,所以輸出應該為 7。
資料規模與約定
對於 80%的資料,1≤a≤b≤10^3。
對於 100% 的資料,1≤a≤b≤10^5,2≤p≤b。
先來康康篩選法篩素數:
#include
#include
using
namespace std;
#define max 5000005
int ip[max]
,p[max]
;//p陣列裡面存素數,ip[i]如果等於0,則i為素數
void
prime
(int n)}}
intmain()
可以看到,篩選法是可以在o(n*lgn)的時間複雜度內算出第100001個素數。
但是也有缺點:如果n足夠大,因為開不了足夠大的陣列而爆掉。
最多允許o(n*lgn)的時間複雜度。
質因數,所以要判斷素數,不能是o(n^2)又因為是連續的數,所以想到篩選法。可以邊篩邊存並查集。
我太難了
乙個並查集中存同乙個集合的數。
並起來的條件:當質因數能被同乙個質數整除(即他們屬於同乙個集合)且兩個數當時屬於不同的集合時,將兩個集合並起來。
喜聞樂見的 **:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace std;
#define ll long long
int f[
100300
],flag[
100300];
//flag為1則為合數,不用進行迴圈
intfind
(int n)
void
insert
(int m,
int n)
intmain()
for(i=
2;i<=r;i++)}
}}else}}
} cout<}
P1621 集合 尤拉篩 並查集
題目鏈結 這個題要求我們在乙個區間 a,b 中找出幾個集合,集合中的數滿足是乙個大於等於p的質因數的個數。看到集合這個定義,我們瞬間會想到用並查集來維護這個集合,那麼對於這個集合,他滿足乙個性質,就是如果我們,起始的時候初始化每乙個數的父親都是自己,那麼每乙個集合中有且只有乙個數的父親 是自己。根據...
演算法 合併集合(並查集)
假如有n個集合,要進行對集合的合併或者判斷兩個數是否在同乙個集合中就要用到並查集。int find x 我們用p x x來判斷當前節點是否為根節點。如果當前節點不是根節點,就進行遞推,繼續呼叫find x 直到找到根節點,之後會進行路徑壓縮,讓根節點的所有子節點都指向根節點。返回值是當前節點的根節點...
51NOD 1821 最優集合 並查集
傳送門 題意 乙個集合s的優美值定義為 最大的x,滿足對於任意i 1,x 都存在乙個s的子集s 使得s 中元素之和為i。給定n個集合,對於每一次詢問,指定乙個集合s1和乙個集合s2,以及乙個數k,要求選擇乙個s2的子集s3 s3 k 使得s1 s3的優美值最大。集合元素可以重複 n,m le 100...