/* 返回顶部 */

P4318 完全平方数

gate

计算第\(K\)个不含完全平方因子的数。

利用容斥原理,计算时,需要减去\(2^2,3^2,5^2...\),加上\(6^2,10^2,15^2...\),减去\(30^2...\)

即,
$ans(n) =n\ -\ $含\(1\)个质因子平方的数 \(+\)\(2\)个质因子平方的数 \(-\)\(3\)个质因子平方的数\(...\)

可以看出,容斥系数即为\(\mu(i)\).

\(i^2>n\)时,个数\(\dfrac{n}{i^2}=0\),显然枚举的上界为\(\sqrt n\)

需要整除分块。

\[ans(n)=\sum_{i=1}^{i\le \sqrt n}\mu(i)\lfloor \frac{n}{i^2}\rfloor \]

二分答案,检查是否有\(ans(mid) > K\)

注意:

这道题很多地方没有给确定的范围,所以最好一开始把数组开的大一点,估算不出来的话就试一试...

code

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;

#define int long long

const int maxn = 5e4+10;
const int N = 5e4;

int T,k,ans,cnt;
int prime[maxn],mu[maxn];
bool vis[maxn];

void Prime(){
    mu[1] = 1;
    for(int i = 2;i <= N;i++){
        if(!vis[i]){
            prime[++cnt] = i;
            mu[i] = -1;
        }
        for(int j = 1;j <= cnt && i*prime[j] <= N;j++){
            vis[i*prime[j]] = true;
            if(i % prime[j] == 0) break;
            mu[i*prime[j]] = -mu[i];
        }
    }
}

bool check(int x){
    int sum = 0;
    for(int i = 1;i*i <= x;i++)
        sum += mu[i] * (x/(i*i));
    return sum >= k;
}

signed main(){
    scanf("%lld",&T);
    Prime();
    for(int i = 1;i <= T;i++){
        scanf("%lld",&k);
        int l = 1,r = k<<1;
        while(l <= r){
            int mid = (l+r)/2;
            if(check(mid)){
                ans = mid;
                r = mid-1;
            }
            else l = mid+1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2020-07-24 09:57  Mogeko  阅读(119)  评论(0编辑  收藏  举报