问题 A: 结队
时间限制: 1 Sec 内存限制: 128 MB
[提交] [状态]
题目描述
众所周知,小X是一个风流倜傥、有极高人格魅力的奆老。
奆老总喜欢挑战高难度的事情,幻想着横穿和自己一样大名鼎鼎的亚马逊雨林。
这个幻想了7083年的事情终要变为现实,小X高兴得连灌两盆洗脚水。
“啊……真香……该死的甜美…………”
古代著名学者度娘在《百度百科》一书中说到:
亚马逊热带雨林(AmazonRainForest)位于南美洲的亚马逊平原,占地550万平方公里。雨林横越了9个国家:巴西(占森林60%面积)、哥伦比亚、秘鲁、委内瑞拉、厄瓜多尔、玻利维亚、圭亚那、苏里南以及法国(法属圭亚那),占据了世界雨林面积的一半,占全球森林面积的20%,是全球最大及物种最多的热带雨林。
小X万年一遇地被吓尿了。他感到面临着生命危险,需要小弟来保护,而自己的小弟实在是太少了,小X灵机一动,想到JSOI的夏令营中有很多dalao。小X照照镜子,被自己的人格魅力深深折服,信心满满。
[9102年8月8日,江苏省常州高级中学]
刚下车,小X身旁就围了一大群猛男。
“小X最帅!”
没有想到的是,小X居然被秀了。省中的dalao早已准备在这一天组成帮派。
省中的dalao从1~n进行编号。小X口味独特,只想让[a,b]区间内的dalao做自己的小弟。
dalao遵循以下规则组成帮派:
最初每个人都自成帮派。组帮派时,对于序号为m,n两个属于不同帮派的dalao,如果m,n有大于等于p的公共质因数,那么m,n所在的帮派就会合并为同一帮派。合并过后的帮派会继续合并,直至没有可以合并的帮派。
小X作为一个奆老,秉承着装弱的传统。他需要你告诉他,一共会有多少不同的帮派。
输入
一行,三个正整数A,B,P。(保证A≤B)
输出
一个正整数,表示最终的帮派个数。
样例输入 Copy
10 20 3
样例输出 Copy
7
提示
样例解释
对于[10,20]中的dalao,可分成如下帮派:
{10,20,12,15,18} {11} {13} {14} {16} {17} {19}
【数据范围】
对于30%的数据,保证有0≤A≤B≤100,P≤100
对于60%的数据,保证有0≤A≤B≤3000,P≤3000
对于100%的数据,保证有0≤A≤B≤50000,P≤50000
思路:”并查集+数学
因为他要分堆 就是一堆一堆 这一堆中两个数的最大质因数大于要求的值就放在一起,就是把这两个数连在一起。所以需要用并查集。
还有一点就是 最大质因数。 这个不一定是最大公约数,因为如果是合数他就不是结果,所以要分解一遍这个数,分解成质数;唯一分解定理就OK了。小于p 的数 约数一定会小于p不用考虑,一律单独放。
#include <map>
#include <queue>
#include <string>
#include<iostream>
#include<stdio.h>
#include<string.h>
#include <algorithm>
#include <math.h>
typedef long long ll;
using namespace std;
const int maxn=2e5+1010;
#define inf 0x3f3f3f3f
const int mod=998244353;
const int MOD=10007;
inline int read() {
int x=0;
bool t=false;
char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
priority_queue<ll , vector<ll> , greater<ll> > mn;//上 小根堆 小到大
priority_queue<ll , vector<ll> , less<ll> > mx;//下 大根堆 大到小
map<ll,ll>mp;
ll n,m,t,l,r,p;
ll sum,ans,res,cnt,flag,maxx,minn;
bool isprime[maxn];
ll a[maxn],b[maxn],c[maxn];
ll dis[maxn],vis[maxn];
ll dp[1010][1010];
string str,s;
vector <ll>v[maxn];
ll f(ll x) {
if(dis[x]==x) return x;
else return dis[x]=f(dis[x]);
}
void so(ll x){
ll y=x;
for(int i=2;i*i<=x;i++){
if(x%i==0){
v[i].push_back(y);
while(x%i==0) x/=i;
}
}
if(x>1) v[x].push_back(y);
}
int main(){
cin>>n>>m>>p;
for(int i=1;i<=m;i++)
dis[i]=i;
for(int i=n;i<=m;i++)
so(i);
for(int i=m;i>=p;i--){
l=v[i].size();
if(l==0) continue;
ans=f(v[i][0]);
for(int j=1;j<l;j++)
{
cnt=f(v[i][j]);
dis[cnt]=ans;
}
}
for(int i=n;i<=m;i++)
if(dis[i]==i) sum++;
cout<<sum<<endl;
return 0;
}