[bzoj2440]完全平方数[中山市选2011][莫比乌斯函数][线性筛][二分答案]

时间:2021-04-03 14:37:30

题意:求第k个分解质因子后质因子次数均为一的数,即求第k个无平方因子数。

题解:

  首先二分答案mid,那么现在就是要求出mid以内的无平方因子数的个数。

  其次枚举$\sqrt{mid}$内的所有质数,由容斥原理

    $Num=0个质数平方的倍数的数量(1的倍数)-1个质数平方的倍数的数量(9,25...的倍数)$

      $+2个质数平方的倍数的数量(36,100...的倍数)...$

  可以发现对于一个数x,x的倍数数量对答案的贡献符号为$\mu(x)$。

  例如:9的倍数数量最答案的贡献是$\mu(9)\lfloor{\frac{mid}{9}}\rfloor=-\lfloor{\frac{mid}{9}}\rfloor$

  所以最终mid以内的个数为

    $Cnt=\sum\limits^{\lfloor{\sqrt{mid}}\rfloor}_{i=1}(\mu(i)\lfloor{\frac{mid}{i^2}}\rfloor)$

  其中莫比乌斯函数为积性函数所以可以用线性筛预处理。

 1 #include <bits/stdc++.h>
2
3 using namespace std;
4
5 int T,n,p[51000],Mu[51000],noprime[51000];
6 bool visited[51000];
7
8 void Mobius(const int N)
9 {
10 int pnum=0; Mu[1]=1;
11 for(int i=2;i<N;i++)
12 {
13 if(!visited[i]) { p[pnum++]=i; Mu[i]=-1; }
14 for(int j=0;j<pnum && i*p[j]<N;j++)
15 {
16 visited[i*p[j]]=true;
17 if(i%p[j]==0) { Mu[i*p[j]]=0; break; }
18 Mu[i*p[j]]=-Mu[i];
19 }
20 }
21 }
22
23 int Check(const int x)
24 {
25 int temp=sqrt(x),Ans=0;
26 for(int i=1;i<=temp;++i)
27 Ans+=Mu[i]*(x/i/i);
28 return Ans;
29 }
30
31 int main()
32 {
33 scanf("%d",&T); Mobius(50000);
34 while(T--)
35 {
36 scanf("%d",&n);
37 int l=0,r=2e9;
38 while(l<r-1)
39 {
40 int mid=l+((r-l)>>1);
41 if(Check(mid)>=n)r=mid;
42 else l=mid;
43 }
44 printf("%d\n",r);
45 }
46 return 0;
47 }