LOJ528 「LibreOJ β Round #4」求和
先按照最常规的思路推一波:
[egin{aligned}
&sum_{i=1}^nsum_{j=1}^mmu^2(gcd(i,j))\
=&sum_{d=1}^{min(n,m)}mu^2(d)sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=d]\
=&sum_{d=1}^{min(n,m)}mu^2(d)sum_{t=1}^{min(n,m)}mu(t)lfloor frac{n}{dt}
floor lfloor frac{m}{dt}
floor\
=&sum_{x=1}^{min(n,m)}lfloor frac{n}{x}
floor lfloor frac{m}{x}
floorsum_{d|x}mu^2(d)mu(frac x d)
end{aligned}
]
然后后面这个东西一定是个积性函数,所以可以求出质数及其幂次上的的值,最后整除分块即可。
然后有另一种更为简洁的思路:
有反演公式 (mu^2(x)=sum_{d^2|x}mu(d))。
考虑证明。
若 (x) 为 ( exttt{square_free numbers}),即其无平方因子,则 (d) 只能取 (1),显然成立。
若 (x) 有 ( exttt{square_free numbers}),即其有平方因子,则左边显然为 (0)。
设其含有某个平方因子 (p_k)。
则对于所有的 (d^2),其中若 (d) 含有 (p^2),其对答案的贡献为 (0)。
否则 (d) 含有 (p) 或不含 (p),显然这两种情况的个数相同,且根据莫比乌斯函数的定义,对于答案的贡献恰好相反,也就是贡献和为 (0)。
所以有
[egin{aligned}
&sum_{i=1}^nsum_{j=1}^mmu^2(gcd(i,j))\
=&sum_{i=1}^nsum_{j=1}^msum_{d^2|gcd(i,j)}mu(d)\
end{aligned}
]
然后你发现我们只需要找到 (gcd(i,j)) 为完全平方数或其倍数的数,所以我们直接枚举就好了。
/*---Author:HenryHuang---*/
/*---Never Settle---*/
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll maxn=4e6+5;
const ll mod=998244353;
ll P;
ll pri[maxn],mu[maxn],p[maxn],cnt;
void init(){
mu[1]=1;
for(ll i=2;i<=P;++i){
if(!p[i]) pri[++cnt]=i,mu[i]=-1;
for(ll j=1;j<=cnt&&pri[j]*i<=P;++j){
p[pri[j]*i]=1;
if(i%pri[j]==0){
mu[pri[j]*i]=0;
break;
}
else mu[pri[j]*i]=-mu[i];
}
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
ll n,m;cin>>n>>m;
if(n<m) swap(n,m);P=sqrt(n+0.5);init();
ll ans=0;
for(ll i=1;1ll*i*i<=n;++i){
if(!mu[i]) continue;
ll x=i*i;
ans=(ll)(ans+mu[i]*(1ll*(n/x)%mod*((m/x)%mod))%mod+mod)%mod;
}
cout<<ans<<'
';
return 0;
}