莫比乌斯反演/乱搞
题目要我们求
主要是求
我们设
那么原式
很容易发现
有两种做法通过 求 :
一:乱搞。发现 ,那么从后往前推求出 即可。
二:反演。套公式可得 ,直接枚举即可。
代码:
//乱搞
#include<cstdio>
#include<algorithm>
#define N 100005
using namespace std;
typedef long long LL;
LL f[N],ans,n,m;
int main(){
scanf("%lld%lld",&n,&m);
if (n>m) swap(n,m);
for (int i=n;i;i--){
f[i]=(n/i)*(m/i);
for (int j=i<<1;j<=n;j+=i) f[i]-=f[j];
ans+=((i<<1)-1)*f[i];
}
return printf("%lld\n",ans),0;
}
//反演
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
using namespace std;
typedef long long LL;
int n,m,mu[N],p[N];
LL ans;
bool f[N];
inline void mkp(){
mu[1]=1;
for (int i=2;i<=n;i++){
if (!f[i]) p[++p[0]]=i,mu[i]=-1;
for (int j=1,v;j<=p[0]&&(v=i*p[j])<=n;j++){
f[v]=true,mu[v]=-mu[i];
if (!(i%p[j])) { mu[v]=0; break; }
}
}
}
int main(){
scanf("%d%d",&n,&m);
if (n>m) swap(n,m); mkp();
for (int i=1;i<=n;i++)
for (int j=i;j<=n;j+=i)
ans+=1ll*mu[j/i]*(1ll*n/(1ll*j))*(1ll*m/(1ll*j))*((i<<1)-1);
return printf("%lld\n",ans),0;
}