1. 程式人生 > 實用技巧 >P4318 完全平方數

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