[中山市选2011] 完全平方数

[题目链接]

          https://www.lydsy.com/JudgeOnline/problem.php?id=2440

[算法]

          首先 , 不妨二分答案mid , 我们需要判断的是一个形如"[1 , mid]区间中是否有 >= k个不是完全平方数倍数的数“

          考虑容斥 , 显然  , 答案为 : mid - 有1个质因子的数的倍数个数 + 有两个质因子的数的倍数个数 - ... + ....

          不难发现 , 每一项的系数为其莫比乌斯函数

          预处理莫比乌斯函数即可

          时间复杂度 : O(NlogN)

[代码]

       

#include<bits/stdc++.h>
using namespace std;
#define MAXD 1000010
typedef long long LL;

LL k;
int miu[MAXD];
bool visited[MAXD];

template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;    
}
inline void preprocess()
{
    for (int i = 1; i < MAXD; i++) 
    {
        miu[i] = 1;
        visited[i] = false;
    }
    for (int i = 2; i < MAXD; i++)
    {
        if (visited[i]) continue;
        miu[i] = -1;
        for (int j = 2; 1LL * i * j < MAXD; j++)
        {
            visited[i * j] = true;
            if (j % i == 0) miu[i * j] = 0;
            else miu[i * j] *= -1;    
        }        
    }
}
inline LL calc(LL mid)
{
    LL ret = 0;
    for (int i = 1; 1LL * i * i <= mid; i++) ret += 1LL * miu[i] * (1LL * mid / (1LL * i * i));
    return ret;
}

int main()
{
    
    int T;
    read(T);
    preprocess();
    while (T--)
    {
        read(k);
        LL l = 1 , r = (LL)1e10 , ans;
        while (l <= r)
        {
            LL mid = (l + r) >> 1;
            if (calc(mid) >= k)
            {
                ans = mid;
                r = mid - 1;
            } else l = mid + 1;
        }
        printf("%lld\n" , ans);
    }
    
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/evenbao/p/9891171.html