第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 }