【BZOJ2440】[中山市选2011] 完全平方数(莫比乌斯函数容斥)
大致题意: 求第\(n\)个不含平方因子的数。
二分+容斥
显然,这东西一看就是满足可二分性的,且二分明显能让题目简单许多。
(说实话,我第一眼看到这东西想到的是二分后杜教筛筛出\(\sum\mu^2(x)\),但觉得这个方法虽然可以是可以,却实在太复杂了。)
实际上,我们只要用容斥,就能求出当前是第几个不含平方因子的数了。
考虑用数的总数减去只含一个质数的平方因子的数的个数加上含两个质数的平方因子的数的个数再减去含三个质数的平方因子的数的个数再加上......
然后发现就相当于是用含偶数个质数的平方因子的数的个数减去含奇数个质数的平方因子的数的个数。
于是我们就想到\(\mu(x)\)的定义,此处恰好可以用作容斥系数,得到式子:
\[\sum_{i=1}^{\sqrt n}\mu(i)\times\lfloor\frac n{i^2}\rfloor
\]
这样一来这道题就做完了。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
using namespace std;
int n;
class LinearSieve
{
private:
#define S 100000
int Pt,P[S+5],mu[S+5];
public:
I int operator [] (CI x) Con {return mu[x];}
I LinearSieve()//线性筛筛μ
{
mu[1]=1;for(RI i=2,j;i<=S;++i)
for(!P[i]&&(mu[P[++Pt]=i]=-1),j=1;j<=Pt&&i*P[j]<=S;++j)
if(P[i*P[j]]=1,i%P[j]) mu[i*P[j]]=-mu[i];else break;
}
}Mu;
I bool Check(CI x)//验证
{
RI i,t=0;for(i=1;i*i<=x;++i) t+=Mu[i]*(x/i/i);//容斥
return t>=n;
}
int main()
{
RI Tt,l,r,mid;scanf("%d",&Tt);W(Tt--)
{
scanf("%d",&n),l=1,r=2*n;//初始化边界
W(l<r) Check(mid=l+(r-l-1>>1))?r=mid:l=mid+1;printf("%d\n",r);//二分
}return 0;
}
待到再迷茫时回头望,所有脚印会发出光芒