Description

求第k个无平方因子数。无平方因子数指分解之后所有质因数的次数都为1的数。

Solution

我们可以进行二分操作,查找区间[1,x]里有几个无平方因子数,逐渐缩小范围依次求解。
然而怎么计算区间[1,x]内无平方因子数的个数Q呢?
根据容斥原理

Q=xx内有一个平方因子的数+x内有两个平方因子的数x内有三个平方因子的数...=xx(4的倍数个数+9的倍数的个数+25的倍数的个数)+x(36(2323)的倍数+100(2525)的倍数)...=i=2x±ni2\begin{align} Q & =x-x内有一个平方因子的数+x内有两个平方因子的数-x内有三个平方因子的数... \\ & = x-x内(4的倍数个数+9的倍数的个数+25的倍数的个数)+x内(36(2*3*2*3)的倍数+100(2*5*2*5)的倍数)... \\ & = \sum_{i=2}^{\sqrt{x}}\pm\frac{n}{i^2} \end{align}

现在的问题是,对于某个n/(i*i),到底是取正还是取负呢?
我们发现,对于有奇数个质数平方的因子数取正,有偶数个质数平方的因子数取正,仔细一看,这不正是i的莫比乌斯函数值吗?于是可求出$$Q=\sum_{i=2}^{\sqrt{x}}\mu(i)\frac{n}{i^2}$$

然后就可以愉快的AC辣!

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include<cmath>
#include<cstdio>

typedef long long ll;
const ll maxx=(ll)1<<32;
const int maxlim=1<<16;

bool form[maxlim];
int mu[maxlim]={0,1},prime[maxlim],cnt;
void MakeMuList(){ //线性筛
for(int i=2;i<maxlim;i++){
if(!form[i]) prime[cnt++]=i,mu[i]=-1;
for(int j=0,t=prime[j]*i;t<maxlim;j++,t=prime[j]*i){
form[t]=true;
if(!(i%prime[j])){ mu[t]=0; break; }
mu[t]=-mu[i];
}
}
}
ll query(ll x){
int lim=sqrt(x);
ll ans=x;
for(int i=2;i<=lim;i++) ans+=mu[i]*(x/(i*i));
return ans;
}
void find(int k){
if(k==1){ printf("1\n"); return; }
int num=0;
ll l=1,r=1644934081,x=0; //r为二分上界
while(l<=r){
ll mid=(l+r)>>1;
num=query(mid);
if(num>=k) r=mid-1,x=mid;
else l=mid+1;
}
printf("%lld\n",x);
}
int main(){
MakeMuList();
int kase; scanf("%d",&kase);
while(kase--){
int k; scanf("%d",&k);
find(k);
}
return 0;
}

Comment