莫比乌斯函数
把题目转化一下,即求 ∑ni=1μ2(i)≥k ∑ i = 1 n μ 2 ( i ) ≥ k 的最小 n n
先二分答案,变成计算
有一个我并不会证明的结论:
μ2(n)=∑d2|nμ(d)
μ
2
(
n
)
=
∑
d
2
|
n
μ
(
d
)
于是推推式子: ∑ni=1μ2(i)=∑ni=1∑d2|nμ(d)=∑n√d=1μ(d)⌊xd2⌋ ∑ i = 1 n μ 2 ( i ) = ∑ i = 1 n ∑ d 2 | n μ ( d ) = ∑ d = 1 n μ ( d ) ⌊ x d 2 ⌋
然后枚 d d <script type="math/tex" id="MathJax-Element-47">d</script>直接算就好了。
代码:
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 40547
using namespace std;
int t,n,mu[N],p[N],c,l,r;
bool f[N];
inline void makep(){
for (int i=2;i<N;i++){
if (!f[i]) p[++c]=i,mu[i]=-1;
for (int j=1,k;j<=c&&(k=p[j]*i)<N;j++){
f[k]=true,mu[k]=-mu[i];
if (i%p[j]==0) { mu[k]=0; break; }
}
}
}
inline int calc(int x){
int sum=0,l=sqrt(x);
for (int i=1;i<=l;i++)
sum+=mu[i]*x/(i*i);
return sum>=n;
}
int main(){
scanf("%d",&t),mu[1]=1,makep();
while (t--){
scanf("%d",&n); int l=1,r=2e9;
while (l<=r){
int mid=(long long)l+r>>1;
if (calc(mid)) r=mid-1;
else l=mid+1;
}
printf("%d\n",l);
}
return 0;
}