题目大意
给出两个数a,b,求满足[x,y]∈[a,b]且x≤y的二元组(x,y)数量。
1≤a≤b≤ 1011
推导过程
这种题显然要莫比乌斯反演!
先不考虑x≤y,最后答案加上b-a+1再除2即可。
然后[a,b]又可以变成区间[1,b]的答案减[1,a-1]的答案。
Ans=∑i=1n∑j=1n[ij(i,j)≤n]
=∑d=1n∑i=1⌊nd⌋∑j=1⌊nd⌋[ijd≤n]∗[(i,j)=1]
接下来套莫比乌斯反演,得到:
Ans=∑d=1n∑d′=1⌊nd⌋μ(d′)∑i=1⌊nd⌋∑j=1⌊nd⌋[ijd≤⌊nd′2⌋]
=∑d′=1n√μ(d′)∑d=1⌊nd′2⌋∑i=1⌊ndd′2⌋∑j=1⌊ndd′2⌋[ijd≤⌊nd′2⌋]
可以发现第一个sigma后面求的是形如[abc≤n]的东西。
令a≤b≤c,那么a只用枚举到
n13
,然后b枚举到
⌊na⌋−−−√
,c的范围可以直接得出。
算出三个数相同、两个数相同,三个数都不同的答案,乘上相应的组合数。
通过积分可以算出时间复杂度是近似于 O(n23) 的
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=316227;
typedef long long LL;
int tot,p[N],mu[N+5];
LL l,r,ans;
bool bz[N+5];
char c;
void init()
{
mu[1]=1;
for (int i=2;i<=N;i++)
{
if (!bz[i])
{
mu[i]=-1; p[tot++]=i;
}
for (int j=0;j<tot;j++)
{
int I=i*p[j];
if (I>N) break;
bz[I]=1;
if (i%p[j]==0)
{
mu[I]=0; break;
}
mu[I]=-mu[i];
}
}
}
LL calc(LL n)
{
if (!n) return 0;
ans=0;
for (int k=1;(LL)k*k<=n;k++) if (mu[k]!=0)
{
LL m=n/((LL)k*k),s=0;
for (int i=1;(LL)i*i*i<=m;i++)
{
for (int j=i+1;(LL)i*j*j<=m;j++)
{
s+=(m/((LL)i*j)-j)*6+3;
}
s+=(m/((LL)i*i)-i)*3+1;
}
if (mu[k]==1) ans+=s;else ans-=s;
}
return (ans+n)/2;
}
int main()
{
init();
scanf("%lld%lld",&l,&r);
printf("%lld\n",calc(r)-calc(l-1));
return 0;
}