P4318 完全平方数 Sol
第一次做莫反题。
这题的二分思路是显然的,那么问题转化成如何快速求 \(\le x\) 的合法数字数量。
不妨考虑容斥。显然的,一个数字合法,当且仅当其质因子出现次数至多为 \(1\),因此可以容斥掉不合法的。
考虑枚举最基础的 \(i\),满足 \(i\) 是合法的,且 \(i > 1\),则如果 \(i\) 的质因数个数为奇数,那么显然就要减去 \(x/(i\times i)\),否则就要加上。想到莫比乌斯函数。
显然的,有 \(f(n) = \sum\limits_{i=1}^{\sqrt n}\mu(i) \cdot \lfloor \frac{n}{i\times i} \rfloor\)。然后做完了。
Code
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
const int N = 40000;
int primes[N],mu[N],tot;
bool vis[N];
void init(){
mu[1] = 1;
for(int i=2;i<N;i++){
if(vis[i] == 0){
primes[++tot] = i;
mu[i] = -1;
}
for(int j=1;j<=tot;j++){
int k = i * primes[j];
if(k >= N) break;
vis[k] = 1;
if(i % primes[j] == 0){
mu[k] = 0;
break;
}
else
mu[k] = -mu[i];
}
}
return ;
}
LL calc(LL x){
LL res = 0;
for(int i=1;i<=N && 1ll * i * i <= x;i++)
res += 1ll * mu[i] * (x / (1ll * i * i));
return res;
}
int main(){
IOS;
init();
int T;
cin >> T;
while(T -- ){
LL k;
cin >> k;
LL l=1,r=(LL)(2e9);
LL ans = -1;
while(l <= r){
LL mid = l + r >> 1;
if(calc(mid) >= k){
ans = mid;
r = mid - 1;
}
else
l = mid + 1;
}
cout << ans << '\n';
}
return 0;
}

浙公网安备 33010602011771号