[Vijos 1889] 天真的因数分解

Posted fly-in-milkyway

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Vijos 1889] 天真的因数分解相关的知识,希望对你有一定的参考价值。

Description

求第 (k)(mu=0) 的数。(k leq 10^{10})

Solution

小于等于 (x) 的无法正确分解的数字个数为:

[- sumlimits_{i=2}^{sqrt x}mu(i){leftlfloorfrac{x}{i^2} ight floor}]

相当于因数中有质数的平方的数,利用 (mu) 函数容斥原理,二分 (x) 进行判断。

注意 (sumlimits_{i=1}^{sqrt n}{leftlfloorfrac{n}{i^2} ight floor}) 的整除分块应该是 (r=sqrt(n / (n / (i * i)))),证明待填坑。

Code

#include <cstdio>
#include <cmath>

typedef long long LL;
const int N = 10000005;
int np[N], p[N], mu[N], sum[N], tot; LL k;

void getmu(int n) {
    for (int i = 2; i <= n; ++i) {
        if (!np[i]) p[++tot] = i, mu[i] = 1;
        for (int j = 1; j <= tot && i * p[j] <= n; ++j) {
            np[i*p[j]] = 1;
            if (i % p[j] == 0) { mu[i*p[j]] = 0; break; }
            mu[i*p[j]] = -mu[i];
        }
    }
    for (int i = 1; i <= n; ++i) sum[i] = sum[i-1] + mu[i];
}
LL calc(LL n) {
    LL res = 0, m = sqrt(n);
    for (LL l = 2, r; l <= m; l = r + 1) {
        r = sqrt(n / (n / (l * l)));
        res += (sum[r] - sum[l-1]) * (n / (l * l));
    }
    return res;
}

int main() {
    scanf("%lld", &k), getmu(1e7);
    LL l = 4, r = 1e14;
    while (l < r) {
        LL mid = l + ((r - l) >> 1);
        LL res = calc(mid);
        if (res >= k) r = mid;
        else l = mid + 1;
    }
    printf("%lld
", l);
    return 0;
}

以上是关于[Vijos 1889] 天真的因数分解的主要内容,如果未能解决你的问题,请参考以下文章

VIJOS 1889 天真的因数分解 ——莫比乌斯函数

Vijos P1786 质因数分解暴力

Vijos——P 1137 组合数

分解因式

分解质因数(解密源代码)

代码实现:将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5