题目要求求出 ∑Na=1∑Nb=a+1[a+b|ab]
我们设 d=gcd(a,b),a=nd,b=md 则转化为
[nd+md|nmd2]=[n+m|nmd] 又有 n,m 互质,则显然有 n+m|d
原式可推为
∑Nd=1∑⌊Nd⌋n=1∑⌊Nd⌋m=n+1e(gcd(n,m))[n+m|d]
[n+m|d]的个数显然为 ⌊Nm(n+m)⌋
e(gcd(n,m)) 显然可以莫比乌斯反演
所以进一步推为
=∑N√m=1∑m−1n=1⌊Nm(n+m)⌋∑d|n,d|mμ(d)
用 md,nd 来替代 m,n 则有
∑N√d=1μ(d)∑⌊N√d⌋m=1∑m−1n=1⌊⌊Nd2m⌋n+m⌋
于是可以分块求得,code:
#include
#include
#include
#include
using namespace std;
long long n,sqn,tot;
long long mu[100001],prime[10001];
bool a[100001];
void prework(long long n)
{
long long i,j;
mu[1]=1;
for (i=2;i<=n;++i)
{
if (!a[i])
{mu[i]=-1; prime[++tot]=i;}
for (j=1;j<=tot&&i*prime[j]<=n;++j)
{
a[i*prime[j]]=true;
if (i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
}
long long work(long long fz,long long n)
{
long long ans=0,i,last;
if (n==0) return 0;
for (i=n+2;i<=2*n+1;i=last+1)
{
if (fz/i==0) break;
last=min(2*n+1,fz/(fz/i));
ans=ans+(last-i+1)*(fz/i);
}
return ans;
}
int main()
{
long long d,m,ans=0,t;
scanf("%lld",&n);
sqn=sqrt(n);
prework(sqn);
for (d=1;d<=sqn;++d)
{
if (mu[d]==0) continue;
t=0;
for (m=2;m<=sqn/d;++m)
t+=work(n/(d*d*m),m-1);
ans=ans+mu[d]*t;
}
printf("%lld\n",ans);
}