bzoj2440: [中山市选2011]完全平方数

自己写的第一个博客。。。。。。。。。

BZOJ 2440

【题意】

  求第K个约数不含平方数的数 (1<=k<=10^9),

  共有T组数据(T<=50)。

【题解】

  首先题解并不是我独立思考的结果(我是蒟蒻qwq)。。。

  设f(n)表示小于等于n的满足所求数性质的数的个数,显然满足单调性,所以可以考虑二分答案吧。

  然后考虑求出f(n)。

  怎么求呢?利用容斥思想,减去含1个质数乘积平方因数的数个数,加上含2个质数乘积平方因数的数个数,再减去含三个质数乘积平方因数的数个数……

  简单来说就是$\sum_{i= 1}^{\left \lfloor \sqrt{n} \right \rfloor}μ\left ( i \right )\cdot  \left \lfloor \frac{n}{i^{2}} \right \rfloor$,

  μ函数就是容斥系数,如果n的约数中同个质数的指数大于1,μ(n)值为0,含奇数个质数约数就为-1,含偶数个就为1。

  μ函数的话可以用线性筛预处理出吧。

  答案不会超过2*n,神奇啊(我是蒟蒻不会证)。。。

  时间复杂度O(T*sqrt(n))

【代码】

 1 #include <cstdio>
 2 #include <iostream>
 3 #define N 50010
 4 using namespace std;
 5 int Q,l,r,o,n,mu[N],prime[N],cnt;
 6 bool flag[N];
 7 void Pre()
 8 {
 9     mu[1]=1;
10     for (int i=2;i<N;++i)
11     {
12         if (!flag[i])    prime[++cnt]=i,mu[i]=-1;        
13         for (int j=1;j<=cnt;++j)            
14         {
15             if (i*prime[j]>=N)    break;
16             flag[i*prime[j]]=1;
17             if (i%prime[j]==0)    break;
18             mu[i*prime[j]]=-mu[i];
19         }
20     }
21 }
22 bool check()
23 {
24     int tot=0;
25     for  (int i=1;i<N && (long long)i*i<=o;++i)
26         tot+=o/(i*i)*mu[i];
27     return tot>=n;
28 }
29 int main()
30 {
31     cin>>Q;
32     Pre();
33     while (Q--)
34     {
35         l=0,r=2e9;
36         cin>>n;
37         while (l<r)
38         {
39             o=((long long)l+r)>>1;            
40             if (check())    r=o;
41             else l=o+1;            
42         }
43         cout<<l<<endl;
44     }
45     return 0;
46 }
View Code
原文地址:https://www.cnblogs.com/Bleacher/p/6764030.html