BZOJ 2986: Non-Squarefree Numbers [容斥原理 二分]

时间:2022-04-11 16:22:35

题意:求第\(n \le 10^{10}\)个不是无平方因子数


二分答案,

容斥一下,0个质数的平方因子-1个.....

枚举\(\sqrt{mid}\)的平方因子乘上莫比乌斯函数,最后求出无平方因子数的个数取补集

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=3e5+5;
typedef long long ll;
inline ll read(){
char c=getchar();ll x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
} ll k;
int notp[N], p[N], mu[N];
void sieve(int n) {
mu[1] = 1;
for(int i=2; i<=n; i++) {
if(!notp[i]) p[++p[0]] = i, mu[i] = -1;
for(int j=1; j<=p[0] && i*p[j]<=n; j++) {
notp[i*p[j]] = 1;
if(i%p[j] == 0) {mu[i*p[j]]=0; break;}
mu[i*p[j]] = -mu[i];
}
}
}
bool check(ll n) {
ll m=sqrt(n), ans=0; //printf("hi %lld %lld\n",n,m);
for(ll i=1; i<=m; i++) ans += mu[i]*(n/(i*i));
ans = n-ans; //printf("check %lld %lld\n",n,ans);
return ans>=k;
}
int main() {
freopen("in","r",stdin);
sieve(N-1);
k=read();
ll l=1, r=k<<2, ans=0;
while(l<=r) {
ll mid = (l+r)>>1;
if(check(mid)) ans=mid, r=mid-1;
else l=mid+1;
}
printf("%lld\n",ans);
}