ac数论之容斥原理与二分枚举--第k个互质数

第k个互质数

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4
描述
两个数的a,b的gcd为1,即a,b互质,现在给你一个数m,你知道与它互质的第k个数是多少吗?与m互质的数按照升序排列。
输入
输入m ,k (1<=m<=1000000;1<=k<=100000000)
输出
输出第k个数。
样例输入
10 1
10 2
10 3
样例输出
1
3

7

#include<iostream>
#include<vector>
using namespace std;
vector<int> yinzi;
int m,k;
void fetch(int mm)
{
    for(int i=2;i*i<=m;i++)
    {
        if(mm%i==0)
        {
            yinzi.push_back(i);
            while(mm%i==0)
                mm/=i;
        }
    }
    if(mm>1)//如果自己是质数那么把自己添加
        yinzi.push_back(mm);
}
int cnt(int top)
{
  int sum=top;
  int t[1000];
  int g=0;
  t[g++]=1;//奇数个或者偶数个因子数目
  for(int i=0;i<yinzi.size();i++)
  {
      int tt=g;
      for(int j=0;j<g;j++)
      {
          t[tt++]=(-1*yinzi[i]*t[j]);//偶数个质因子为正,奇数个质因子为负
          sum+=top/t[tt-1];//计算[1,n]之间有多少数含有因子b[t]
      }
      g=tt;
  }
  return sum;
}
//二分枚举答案mid,计算[1,mid]内有多少个数与m互质,并将其结果与k比较
int Binary_search()//相当于一个二分查找,找到这个mid,如果1到mid区间内的与m的互质数大于或者等于k那么区间下移来逼近第k个,如果1到mid区间内的与m的互质数小于k说明区间小了,那么区间上移来逼近第k个互质数
{
    int le=0;
    long long ri=1000000000;//因为是10位了,于是我就定义一个long long

    while(le<=ri)
    {
        int mid=(le+ri)/2;
        if(cnt(mid)>=k)
        {
            ri=mid-1;
        }
        else
            le=mid+1;
    }
    return le;//由于mid的每次计算都是下取整的所以返回le
}
int main()
{
    while(cin>>m>>k)
    {
        yinzi.clear();
        fetch(m);
        cout<<Binary_search()<<endl;
    }
}

猜你喜欢

转载自blog.csdn.net/memeda1141/article/details/80024160