题解 P5438 【【XR-2】记忆】
题目大意
求
[l,r] 形成的排列中,相邻两个数的乘积是完全平方数的对数最多是多少。
前置知识
- 线性筛
- 整除分块
- 莫比乌斯函数
- 容斥
题解
将正整数
易知两个数乘起来为完全平方数,当且仅当这两个数除去各自的最大平方因子后相等。
我们首先考虑
考虑一个数
因此,我们所求的答案等价于
再考虑
它与
因此现在只需要计算
我们可以枚举
代码
#include<bits/stdc++.h>
#define N 10000010
#define ll long long
using namespace std;int crr;
int nop[N],p[N],mu[N],cnt,s[N],s2[N];
void mem(int n)
{
mu[1]=1;for (int i=2;i<=n;i++)
{
if (!nop[i]) p[++cnt]=i,mu[i]=-1;
for (int j=1;j<=cnt && i*p[j]<=n;j++)
{
nop[i*p[j]]=1;if (i%p[j]==0){mu[i*p[j]]=0;break;}mu[i*p[j]]=-mu[i];
}
}
for (int i=1;i<=n;i++) s[i]=s[i-1]+mu[i],s2[i]=s2[i-1]+mu[i]*mu[i];
}
ll sol(ll x)
{
if (x<=N-10) return x-s2[x];
ll ans=0,p,m=sqrt(x),i;
for (i=2;i<=m;i=p+1)
{
p=min((ll)(sqrt(x/(x/(i*i)))),m);
ans-=x/(i*i)*(s[p]-s[i-1]);
}
return ans;
}
int main()
{
mem(N-10);ll l,r,i,ans,lst=0;cin>>l>>r;
ans=sol(r)-sol(l-1);lst=l-1;
for (i=2;i*i<=r;i++)
{
ll p=(l-1)/(i*i),q=(r)/(i*i);q=min(q,lst);
if (q>p) ans-=(q-p-sol(q)+sol(p));
lst=p;
}
cout<<ans;
}