P1504 - 整數合並
Description
現在給你一些連續的整數,它們是從 A 到 B 的整數。一開始每個整數都屬於各自的集合,然后你需要進行如下操作:
每次選擇兩個屬於不同集合的整數,如果這兩個整數擁有大於等於 P 的公共質因子,那么把他們所在的集合合並。
反復上述操作,直到沒有可以合並的集合為止。
現在,小 X 想知道,最后有多少個集合。
Input
一行,三個整數 A,B,P
Output
一個數,表示最終集合的個數。
Sample Input
10 20 3
Sample Output
7
Hint
樣例解釋:
解釋: {10 , 20 , 12 , 15 , 18} , {11},{13} , {14} , {16} , {17} , {19}
【數據規模】
B<=1000. 80%數據
A<=B<=100000; 2<=P<=B
可以先用歐拉篩把小於b的素數都篩出來,然后每個素數的倍數肯定都是一個集合的,
然后某個數的素因數如果不止一個,那還可以和別的集合合並成一個集合。
枚舉素數的時候可以搞一個標記,表示這個素數的集合對答案有沒有貢獻,
若在枚舉這個素數的倍數的時候發現某個數是已經有找出來的質因數,
那么這個素數集合肯定可以和前面的那個素數集合合並,
所以這個素數集合對答案是沒有貢獻的。在最后還要把答案加上那些沒有找到質因子的數的數量。
具體實現看代碼
1 #include<set> 2 #include<map> 3 #include<queue> 4 #include<stack> 5 #include<ctime> 6 #include<cmath> 7 #include<string> 8 #include<vector> 9 #include<cstdio> 10 #include<cstdlib> 11 #include<cstring> 12 #include<iostream> 13 #include<algorithm> 14 #define maxn 100010 15 using namespace std; 16 bool bj[maxn]; 17 int su[maxn]; 18 vector<int>from[maxn]; 19 int main() 20 { 21 freopen("!.in","r",stdin); 22 freopen("!.out","w",stdout); 23 int a,b,p,sum=0; 24 scanf("%d%d%d",&a,&b,&p); 25 for(int i=2;i<=b;i++){ 26 if(bj[i]==0) su[++sum]=i; 27 for(int j=1;j<=sum;j++){ 28 if(su[j]*i>b) break; 29 bj[su[j]*i]=1; 30 if(i%su[j]==0) break; 31 } 32 } 33 int ans=0; 34 for(int i=1;i<=sum;i++){ 35 if(su[i]<p) continue; 36 int y=a/su[i]*su[i]; 37 while(y<a) y+=su[i]; 38 int f=1;if(y>b) f=0; 39 while(y<=b){ 40 if(from[y].size()>0) f=0; 41 from[y].push_back(i); 42 y+=su[i]; 43 } 44 ans+=f; 45 } 46 for(int i=a;i<=b;i++) if(from[i].size()==0) ans++; 47 printf("%d",ans); 48 return 0; 49 }
