第k个互质数(二分 + 容斥)

描述两个数的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

首先对m进行质因数分解,求出m有哪些质因数,然后用容斥求[1, mid]内与m互质的数有多少个。

判断的时候,[1,mid]之间与m互质的数的数量 = mid - (包含一个质因子的数的个数)+ (包含2个质因子的书的个数)-(包含3个质因子的数的个数)+ (包含4个质因数的数的个数)……

 1 #include <cstdio>  
 2 // 对n进行素因子分解, fac[0]记录因子个数;  
 3 int fac[20];  
 4 void Div(int n) {  
 5     int k = 0;  
 6     for(int i = 2; i * i <= n; ++i){  
 7         if(n % i == 0) fac[++k] = i;  
 8         while(n % i == 0) n /= i;  
 9     }  
10     if(n > 1) fac[++k] = n;  
11     fac[0] = k;  
12 }  
13 // 计算[1, n]内与m互质的数的个数  
14 int que[1<<10];  
15 int Count(int n, int m) {  
16     int g = 0, sum = n;  
17     que[++g] = 1;  
18     for(int i = 1; i <= fac[0]; ++i){  
19         int t = g;  
20         for(int j = 1; j <= g; ++j){  
21             que[++t] = que[j] * fac[i] * -1;  
22             sum += n / que[t];  
23         }  
24         g = t;  
25     }  
26     return sum;  
27 }  
28 // 二分,二分枚举一个答案mid,计算[1, mid]内有多少个数与m互质,让答案与K比较;  
29 int Binary_search(int m, int K){  
30     int l = 1, r = 2000000000, mid;  
31     while(l <= r){  
32         mid = (l + r) >> 1;  
33         if(Count(mid, m) >= K) r = mid - 1;  
34         else l = mid + 1;  
35     }  
36     return l;  
37 }  
38 int main()  
39 {  
40     int m, K;  
41     while(scanf("%d%d", &m, &K) != EOF)  
42     {  
43         Div(m);  
44         int ans = Binary_search(m, K);  
45         printf("%d\n", ans);  
46     }  
47     return 0;  
48 } 

 

posted @ 2017-12-10 17:33  demianzhang  阅读(768)  评论(0编辑  收藏  举报