自己写的第一个博客。。。。。。。。。
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 }