CF1036F Relatively Prime Powers

题目大意

对于一个数 xx,当且仅当将其分解后各个质因数的指数的最大公约数为 11 时,我们称这个数是合法的。

TT 组数据,对于每组数据,询问区间 [2,n][2,n] 中合法的数的个数。

1T105,2n10181 \leq T \leq 10^5,2 \leq n \leq 10^{18}

解题思路

一个数不是合法的,也就是这个 gcd=k\gcd = k

此时这个数字一定可以被写成 x=ikx=i^k

问题就变成 2n2\sim n 中有多少个数能被表示成 iki^k,其中 k2k\ge 2

考虑莫比乌斯反演。

f(k)f(k) 表示 gcd=k\gcd = k 的数的个数。

F(k)F(k) 表示 gcdk\gcd ∣ k 的数的个数。

显然,F(k)=dkf(d)F(k)=\sum\limits_{d|k}f(d)

根据莫比乌斯反演,我们有 f(x)=xdμ(d)F(dx)f(x)=\sum\limits_{x|d}\mu(d)F(\frac{d}{x})

然后,F(d)=x1/d1F(d)=\lfloor x^{1/d}\rfloor-1

那么 ans=f(1)=μ(d)F(d)ans=f(1)=\sum\mu(d)F(d)

注意精度问题即可。

CODE

#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int N = 100, M = 6e3;

ll prime[N], mu[N], cnt;

bool isprime[N];

ll read()
{
    ll x = 0, f = 1;
    char c = getchar();
    while (!isdigit(c))
    {
        if (c == '-')
            f = -1;
        c = getchar();
    }
    while (isdigit(c))
        x = x * 10 + c - '0', c = getchar();
    return x * f;
}

inline void js(int n)
{
    mu[1] = 1;
    for (int i = 2; i <= n; i++)
    {
        if (!isprime[i])
            prime[++cnt] = i, mu[i] = -1;
        for (int j = 1; j <= cnt && i * prime[j] <= n; j++)
        {
            isprime[i * prime[j]] = 1;
            if (i % prime[j] == 0)
                break;
            mu[i * prime[j]] = -mu[i];
        }
    }
}

#define double long double

ll n;

double qpow(double a, ll b)
{
    if (b == 1)
        return a;
    if (b % 2 == 1)
        return qpow(a, b - 1) * a;
    double temp = pow(a, b / 2);
    return temp * temp;
}

void solve()
{
    n = read();
    ll ans = 0;
    for (int i = 1; i <= 60; i++)
    {
        ll temp = (ll)(pow(n, 1.l / i)) + 1;
        while (qpow(temp, i) > n)
            temp--;
        ans += mu[i] * (temp - 1);
    }
    printf("%lld\n", ans);
}

signed main()
{
    int t = read();
    js(100);
    while (t--)
        solve();
}
posted @ 2021-12-10 13:31  蒟蒻orz  阅读(9)  评论(0)    收藏  举报  来源