1. 程式人生 > >洛谷——P1621 集合

洛谷——P1621 集合

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(int
j=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 集合