P4318 完全平方数
计算第\(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;
}