背景:
上古时代的坑。
题目传送门:
https://www.luogu.org/problemnew/show/P4318
题意:
规定某个完全平方数(1不是完全平方数)的正整数倍是讨厌的数,求第
n
n
n个喜欢的数(无平方因子数,即没有平方数作为因子)。
思路:
根据
P
o
P
o
Q
Q
Q
PoPoQQQ
PoPoQQQ大佬的的
P
P
T
PPT
PPT,我们可以将这个问题二分。
考虑
[
1
,
x
]
[1,x]
[1,x]无平方因子数的数量。
那么这个问题就变成了判定性问题。
我们可以考虑容斥。
对于
x
\sqrt{x}
x以内所有的质数有
x
x
x以内的无平方因子数
=
=
=
0
0
0个质数乘积的平方的倍数的数的数量(
1
1
1的倍数)
−
-
−每
1
1
1个质数的平方的倍数的数的数量(
9
=
3
2
9=3^2
9=32的倍数,
25
=
5
2
25=5^2
25=52的倍数,…)
+
+
+每
2
2
2个质数乘积的平方的倍数的数的数量(
36
=
(
2
∗
3
)
2
36=(2*3)^2
36=(2∗3)2的倍数,
100
=
(
2
∗
5
)
2
100=(2*5)^2
100=(2∗5)2的倍数,…)
…
[
1
,
x
]
[1,x]
[1,x]的
i
2
i^2
i2的倍数一共有
⌊
x
i
2
⌋
\lfloor\frac{x}{i^2}\rfloor
⌊i2x⌋,同时我们发现它的符号为
μ
(
i
)
\mu(i)
μ(i)。则有
a
n
s
=
∑
i
=
1
x
μ
(
i
)
⌊
x
i
2
⌋
ans=\sum_{i=1}^{\sqrt{x}}\mu(i)\lfloor\frac{x}{i^2}\rfloor
ans=∑i=1xμ(i)⌊i2x⌋
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int mu[1000010],prime[1000010];
bool bz[1000010];
int n,t=0;
void init(int ma)
{
mu[1]=1;
bz[0]=bz[1]=true;
for(int i=2;i<=ma;i++)
{
if(!bz[i]) prime[++t]=i,mu[i]=-1;
for(int j=1;j<=t&&i*prime[j]<=ma;j++)
{
bz[i*prime[j]]=true;
if(!(i%prime[j]))
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
}
bool check(int x)
{
int tot=0;
for(int i=1;i*i<=x;i++)
tot+=mu[i]*(x/(i*i));
return tot>=n;
}
int work(int x)
{
int ans,l=1,r=int(2e9),mid;
while(l<=r)
{
mid=(int)(((LL)l+r)>>1);
if(check(mid)) r=mid-1,ans=mid; else l=mid+1;
}
return ans;
}
int main()
{
int T;
init(1000000);
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
printf("%d\n",work(n));
}
}