码迷,mamicode.com
首页 > 其他好文 > 详细

洛谷——P1621 集合

时间:2017-10-16 22:14:35      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:name   一个   大于   输出   集合   ++   cstring   not   include   

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 集合

标签:name   一个   大于   输出   集合   ++   cstring   not   include   

原文地址:http://www.cnblogs.com/z360/p/7678550.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!