完全平方数
前言
刚刚学习了莫比乌斯函数和性质一:
性质一:
\[\sum_{d|n} \mu(d) = [n=1]
\]
\([n=1]\)表示\(n=1\)返回\(1\),否则返回\(0\)
证明
当\(n>1\)时
设\(\omega(n)\)表示\(n\)的不同质因子的个数
\[\begin{aligned}
\sum_{d|n} \mu(d) &= \sum_{i=0}^{\omega(n)} \binom{\omega(n)}{i} (-1)^i \\
&=\sum_{i=0}^{\omega(n)} \binom{\omega(n)}{i} (-1)^i * 1^{\omega(n)-i} \\
\end{aligned}
\]
看到这个就会想到二次式定理:
\[(a+b)^n = \sum_{i=0}^n \binom{n}{i} a^i b^{n-i}
\]
根据二次式定理
可以继续化简
\[\begin{aligned}
&=(-1+1)^{\omega(n)} \\
&=0 \\
\end{aligned}
\]
当\(n=1\)时
不用说\(\mu(1)=1\)
证毕
进入正题
题目大意:\(N\)组数据,求第\(k\)大的不是完全平方数的倍数的数
设\(x\)为不是完全平方数的倍数的数
则\(\mu ^2 (x)=1\)
设
\[f(i)=\max_{d^2|i} d
\]
那么当\(f(i)=1\)时,\(i\)就为不是完全平方数的倍数的数
则从\(1\)到\(n\)的不是完全平方数的倍数的数的个数为
\[\sum_{i=1}^n [f(i)=1]
\]
带入性质一
\[\begin{aligned}
&= \sum_{i=1}^n \sum_{d|f(i)} \mu(d) \\
&= \sum_{i=1}^n \sum_{d^2|i} \mu(d) \\
&= \sum_{d=1} \sum_{d^2|i} \mu(d) \\
&= \sum_{d=1} \mu(d) \sum_{d^2|i} 1 \\
&= \sum_{d=1} \mu(d) \lfloor \frac{n}{d^2} \rfloor \\
\end{aligned}
\]
结束
\(\mu\)的值可以用筛法求出
时间复杂度为\(O(\sqrt n \log n)\)
代码:
#include<cstdio>
#define ll long long
using namespace std;
int mo[400000],p[400000],tot=0,n;
bool vis[400000];
void init()
{
mo[1]=1;
for (int i=2;i<=320000;i++)
{
if (!vis[i]) p[++tot]=i,mo[i]=-1;
for (int j=1;j<=tot&&p[j]*i<=320000;j++)
{
vis[p[j]*i]=true;
if (i%p[j]==0) break;
mo[p[j]*i]=-mo[i];
}
}
}
bool check(ll x)
{
ll res=0;
for (int i=1;i*i<=x;i++)
res+=mo[i]*(x/(i*i));
return res>=n;
}
int main()
{
init();
int t;
scanf("%d",&t);
while (t--)
{
scanf("%d",&n);
ll l=n,r=n<<1;
while (l<r)
{
ll mid=(l+r)>>1;
if (check(mid)) r=mid;
else l=mid+1;
}
printf("%lld\n",r);
}
}