题意
求 ∑i=1n∑j=1mlcm(i,j)(gcd(i,j)无平方质因子) ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) ( g c d ( i , j ) 无 平 方 质 因 子 )
题解
无平方质因子,即
μ2=1
μ
2
=
1
因此式子可以转化为
令 f(x)=∑d|xμ2(d)μ(xd)xd f ( x ) = ∑ d | x μ 2 ( d ) μ ( x d ) x d
g(x)=μ2(x) g ( x ) = μ 2 ( x )
h(x)=μ(x)⋅x h ( x ) = μ ( x ) ⋅ x
因此 f(x)=g(x)∗h(x) f ( x ) = g ( x ) ∗ h ( x ) (卷积)
因为 g(x) g ( x ) 与 h(x) h ( x ) 为积性函数,因此 f(x) f ( x ) 也为积性函数,可以线筛(虽然…我是看不出来的 再见)
在写程序的时候呢,其实可以线筛 D⋅f(x) D ⋅ f ( x ) ,会好做一些
代码
#include <cstdio>
#include <algorithm>
using namespace std;
#define ll long long
#define N 4000010
#define U unsigned int
int tot=0,T,notprime[N],prime[N];
U f[N];
inline void sieve(){
f[1]=1;
for(int i=2;i<=4000000;i++){
if(!notprime[i]) prime[++tot]=i,f[i]=1-i;
for(int j=1;j<=tot && prime[j]*i<=4000000;j++){
notprime[prime[j]*i]=1;
if(i%prime[j]==0){
if(i%(prime[j]*prime[j])==0) f[i*prime[j]]=0;
else f[i*prime[j]]=-f[i/prime[j]]*prime[j];
break;
}f[prime[j]*i]=f[i]*(1-prime[j]);
}
}
for(int i=2;i<=4000000;i++) f[i]=f[i]*i+f[i-1];
}
inline U sum(int x){
return (U)x*(x+1)/2;
}
int main(){
scanf("%d",&T);sieve();
while(T--){
int n,m;scanf("%d%d",&n,&m);
if(n>m) swap(n,m);
U ans=0;
for(int i=1,last;i<=n;i=last+1){
last=min(n/(n/i),m/(m/i));
ans+=(f[last]-f[i-1])*sum(n/i)*sum(m/i);
}
printf("%u\n",ans&0x3fffffff);
}
return 0;
}