==∑i=1n∑j=1n[lcm(i,j)≤n]∑d=1n∑i=1⌊nd⌋∑j=1⌊nid⌋[gcd(i,j)=1]∑x=1nμ(x)∑i∑j∑k[ijk≤nx2]
直接枚举 x ,这一步只需要枚举到
下面来推导一下复杂度。
首先看 f(n) 的复杂度, O(∫n√30nx‾‾√dx)=O(n23) 。
整个问题的复杂度 O(∫n√1(nx2)23dx)=O(n23⋅3(1−1n√6))
,右边一部分是常数,因此复杂度 O(n23) 。
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL long long
const int maxn=400010,mod=10000007,lim=10000010;
int vis[maxn],mu[maxn],prm[maxn],
fir[mod+10],ne[lim],
tot;
LL a,b,mx;
/*struct set
{
int fir[mod+10],ne[lim],tot;
LL val[lim],ans[lim];
LL find(LL n)
{
for (int i=fir[n%mod];i;i=ne[i])
if (val[i]==n) return ans[i];
return 0;
}
void ins(LL n,LL x)
{
if (tot>lim-5) return;
int y=n%mod;
ne[++tot]=fir[y];
fir[y]=tot;
val[tot]=n;
ans[tot]=x;
}
}h2,h3;
LL sum2(LL n)
{
LL ret=h2.find(n);
if (ret) return ret;
for (LL i=1,j;i<=n;i=j+1)
{
j=n/(n/i);
ret+=(j-i+1)*(n/i);
}
h2.ins(n,ret);
return ret;
}
LL sum3(LL n)
{
LL ret=h3.find(n);
if (ret) return ret;
ret=0;
for (LL i=1,j;i<=n;i=j+1)
{
j=n/(n/i);
ret+=(j-i+1)*sum2(n/i);
}
h3.ins(n,ret);
return ret;
}*/
LL sum3(LL n)
{
LL ret=0,x;
for (LL i=1;i*i*i<=n;i++)
{
ret++;
x=n/(i*i);
if (x>i) ret+=(x-i)*3;
for (LL j=i+1;i*j*j<=n;j++)
{
x=n/(i*j);
ret+=(x-j)*6+3;
}
}
return ret;
}
LL solve(LL n)
{
LL ret=0;
for (int i=1;(LL)i*i<=n;i++)
if (mu[i]) ret+=mu[i]*sum3(n/i/i);
return ret;
}
int main()
{
//freopen("a.in","r",stdin);
scanf("%lld%lld",&a,&b);
mx=sqrt(b+0.5);
mu[1]=1;
for (int i=2;i<=mx;i++)
{
if (!vis[i])
{
prm[++tot]=i;
mu[i]=-1;
}
for (int j=1;j<=tot&&(LL)i*prm[j]<=mx;j++)
{
vis[i*prm[j]]=1;
if (i%prm[j]) mu[i*prm[j]]=-mu[i];
else
{
mu[i*prm[j]]=0;
break;
}
}
}
printf("%lld\n",(solve(b)-solve(a-1)+b-a+1)/2);
}