欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

[P4318] 完全平方数

程序员文章站 2022-07-04 12:41:28
想不出什么办法能直接算的(~~别跟我提分块打表~~),不如二分答案吧:设$f(x)=\sum_{i=1}^n [i不是“完全平方数”]$, 显然f(x)与x正相关。再结合筛法、容斥,不难得到: $$ f(x)=\sum_{i=1}^{sqrt x } \mu(i)\lfloor\frac{x}{i^ ......

想不出什么办法能直接算的(别跟我提分块打表),不如二分答案吧:设\(f(x)=\sum_{i=1}^n [i不是“完全平方数”]\), 显然f(x)与x正相关。再结合筛法、容斥,不难得到:
\[ f(x)=\sum_{i=1}^{sqrt x } \mu(i)\lfloor\frac{x}{i^2}\rfloor \]
找到那个满足f(x)==k的x就行了。

#include <bits/stdc++.h>
#define int long long 
using namespace std;
const int n=1e6+10;

int mu[n],pr[n],cnt;
bool vis[n];

void predure() {
    mu[1]=1;
    for(int i=2; i<n; ++i) {
        if(!vis[i]) mu[pr[++cnt]=i]=-1;
        for(int j=1; j<=cnt && i*pr[j]<n; ++j) {
            vis[i*pr[j]]=1;
            if(i%pr[j]==0) break;
            mu[i*pr[j]]=-mu[i];
        }
    }
}
int f(int x) {
    int ret=0;
    for(int i=1; i<=x/i; ++i) {
        ret+=mu[i]*(x/(i*i));
    }
    return ret;
}

signed main() {
    predure();
    int t,k;
    scanf("%lld",&t);
    while(t--) {
        scanf("%lld",&k);
        int l=1,r=k*2,mid,ans;
        while(l<=r) {
            mid=(l+r)>>1;
            if(f(mid)>=k) ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%lld\n",ans);
    }
    return 0;
}