题目描述
题解
刚开始有一个非常傻逼的方法
就是画柿子画成了这个样子
∑T=1ns(nT,mT)∑p(d)|Tμ(p(d)T)(p(d)T)2p(d)
其中 p(d) 表示第 d 个不含平方因子的数
但是这玩意没法筛,只能暴力求卡时过
但其实这道题还有一种更科学的方法
令
然后假设
∑i=1n∑j=1m∑d=1n[(i,j)=d]ijdf(d)
=∑d=1n∑i=1nd∑j=1md[(i,j)=1]ijdf(d)
利用反演公式 [n=1]=∑d|nμ(d)
=∑d=1n∑t=1nd∑i=1nd[t|i]i∑j=1md[t|j]jμ(t)df(d)
令 s(n,m)=∑i=1ni+∑j=1mj
=∑d=1n∑t=1nds(ndt,mdt)t2μ(t)df(d)
令 T=dt ,那么现在 d 为
=∑T=1ns(nT,mT)∑d|Tμ(Td)(Td)2df(d)
令 F(n)=∑d|nμ(nd)(nd)2df(d),f′(d)=df(d),g(n)=∑d|Tμ(Td)(Td)2
那么 F=g×f′ 就是一个狄利克雷卷积的形式
可以发现 g 和
比较简单的是当
当 (a,b)≠1 时,也就是用 F(a) 和 p 推出
可以发现 a 此时最多含有一个质因子
那么我们将 p 先除掉,那么
又因为 F(p2)=−p3 ,所以 F(ap)=F(ap)∗(−p3)
这样就能求出 F 了
那么原式
同样分块。。。
时间复杂度 O(n+T(n−−√+m−−√))
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
using namespace std;
#define Mod 1073741824
#define N 4000005
#define LL long long
int T,n,m,ans;
int p[N],prime[N],mu[N],f[N];
void get(int n)
{
mu[1]=1;
for (int i=2;i<=n;++i)
{
if (!p[i])
{
prime[++prime[0]]=i;
mu[i]=-1;
}
for (int j=1;j<=prime[0]&&i*prime[j]<=n;++j)
{
int t=i*prime[j];
p[t]=1;
if (i%prime[j]==0)
{
mu[t]=0;
break;
}
else mu[t]=-mu[i];
}
}
for (int i=1;i<=n;++i)
if (mu[i])
for (int j=1;j*i<=n;j++) f[j*i]=f[j*i]+mu[j]*j*j*i;
for (int i=1;i<=n;i++) f[i]=f[i]+f[i-1];
}
int calc(int n,int m)
{
return (n*(n+1)>>1)*(m*(m+1)>>1);
}
int main()
{
get(4000000);
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
if (n>m) swap(n,m);
ans=0;
for (int i=1,j=0;i<=n;i=j+1)
{
j=min(n/(n/i),m/(m/i));
ans+=calc(n/i,m/i)*(f[j]-f[i-1]);
}
ans=(ans%Mod+Mod)%Mod;
printf("%d\n",ans);
}
}
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
using namespace std;
#define Mod 1073741824
#define N 4000005
#define LL long long
int T,n,m,ans;
int p[N],prime[N],mu[N],f[N],g[N],t[N];
void get(int n)
{
f[1]=1;
for (int i=2;i<=n;++i)
{
if (!p[i])
{
prime[++prime[0]]=i;
f[i]=i-i*i;
t[i]=1;
}
for (int j=1;j<=prime[0]&&i*prime[j]<=n;++j)
{
p[i*prime[j]]=1;
if (i%prime[j]==0)
{
if (t[i]>=2) f[i*prime[j]]=0;
else
f[i*prime[j]]=-f[i/prime[j]]*prime[j]*prime[j]*prime[j];
t[i*prime[j]]=t[i]+1;
break;
}
else
{
f[i*prime[j]]=f[i]*f[prime[j]];
t[i*prime[j]]=1;
}
}
}
for (int i=1;i<=n;i++) f[i]=f[i]+f[i-1];
}
int calc(int n,int m)
{
return (n*(n+1)>>1)*(m*(m+1)>>1);
}
int main()
{
get(4000000);
scanf("%d",&T);
while (T--)
{
scanf("%d%d",&n,&m);
if (n>m) swap(n,m);
ans=0;
for (int i=1,j=0;i<=n;i=j+1)
{
j=min(n/(n/i),m/(m/i));
ans+=calc(n/i,m/i)*(f[j]-f[i-1]);
}
ans=(ans%Mod+Mod)%Mod;
printf("%d\n",ans);
}
}