题意:
求 ∑ i = 1 n ∑ j = 1 m g c d ( i , j ) \sum_{i=1}^n\sum_{j=1}^mgcd(i,j) ∑i=1n∑j=1mgcd(i,j)
n,m=1e7
O ( N ) O(N) O(N)版本:
换成因子角度,设: g c d ( i , j ) = d , m i n ( n , m ) = N gcd(i,j)=d,min(n,m)=N gcd(i,j)=d,min(n,m)=N,有: A n s = ∑ d = 1 N d ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = = d ] = ∑ d = 1 N d ∑ i = 1 n d ∑ j = 1 m d [ g c d ( i , j ) = = 1 ] Ans=\sum_{d=1}^Nd\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==d]=\sum_{d=1}^Nd\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{m}{d}}[gcd(i,j)==1] Ans=d=1∑Ndi=1∑nj=1∑m[gcd(i,j)==d]=d=1∑Ndi=1∑dnj=1∑dm[gcd(i,j)==1]而 g c d = = d gcd==d gcd==d按照套路可以进行莫比乌斯的倍数反演: g ( d , n , m ) = ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = = d ] 构 造 : f ( d , n , m ) = ∑ d ∣ D g ( D , n , m ) = ∑ i = 1 n ∑ j = 1 m [ d ∣ g c d ( i , j ) ] = [ n d ] [ m d ] 反 演 : g ( d , n , m ) = ∑ d ∣ D m i n ( n , m ) u ( D d ) f ( D ) = ∑ d ∣ D m i n ( n , m ) u ( D d ) [ n D ] [ m D ] 而 我 们 所 求 为 g c d = = 1 , 所 以 : g ( 1 , n , m ) = ∑ i = 1 N u ( i ) [ n i ] [ m i ] A n s = ∑ d = 1 N d ∗ g ( 1 , n d , m d ) A n s = ∑ d = 1 N d ∑ i = 1 N d u ( i ) [ n i ∗ d ] [ m i ∗ d ] g(d,n,m)=\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==d] \\ 构造:f(d,n,m)=\sum_{d|D}g(D,n,m)=\sum_{i=1}^n\sum_{j=1}^m[d|gcd(i,j)]=[\frac{n}{d}][\frac{m}{d}]\\反演:g(d,n,m)=\sum_{d|D}^{min(n,m)}u(\frac{D}{d})f(D)=\sum_{d|D}^{min(n,m)}u(\frac{D}{d})[\frac{n}{D}][\frac{m}{D}]\\而我们所求为gcd==1,所以:g(1,n,m)=\sum_{i=1}^Nu(i)[\frac{n}{i}][\frac{m}{i}]\\Ans=\sum_{d=1}^Nd*g(1,\frac{n}{d},\frac{m}{d})\\Ans=\sum_{d=1}^Nd\sum_{i=1}^\frac{N}{d}u(i)[\frac{n}{i*d}][\frac{m}{i*d}] g(d,n,m)=i=1∑nj=1∑m[gcd(i,j)==d]构造:f(d,n,m)=d∣D∑g(D,n,m)=i=1∑nj=1∑m[d∣gcd(i,j)]=[dn][dm]反演:g(d,n,m)=d∣D∑min(n,m)u(dD)f(D)=d∣D∑min(n,m)u(dD)[Dn][Dm]而我们所求为gcd==1,所以:g(1,n,m)=i=1∑Nu(i)[in][im]Ans=d=1∑Nd∗g(1,dn,dm)Ans=d=1∑Ndi=1∑dNu(i)[i∗dn][i∗dm]同样,到这里两个分块时间复杂度为O(N)
#include
using namespace std;
#define LL long long
const int N = 1e7+9;
const LL mod = 998244353;
LL u[N];
LL pri[N>>1],now;
bool vis[N];
void init(){ //预处理莫比乌斯函数前缀和
vis[1]=1;u[1]=1;
for(int i=2;i<N;i++){
if(!vis[i])pri[++now]=i,u[i]=-1;
for(int j=1;j<=now&&pri[j]*i<N;j++){
vis[pri[j]*i]=1;
u[pri[j]*i]=-u[i];
if(i%pri[j]==0){u[pri[j]*i]=0;break;}
}
}
for(int i=1;i<N;i++)u[i]=u[i]+u[i-1];
}
LL solve(LL n,LL m){
LL ans=0;
LL NN=min(n,m);
for(LL l=1,r;l<=NN;l=r+1){ //[(n/d)/i][(m/d)/i] 分块
r=min(n/(n/l),m/(m/l));
LL re=(u[r]-u[l-1])*(n/l)%mod*(m/l)%mod ;
ans=(ans+re)%mod;
}
return (ans+mod)%mod;
}
int main(){
init();
LL n,m;
while(cin>>n>>m){
LL NN=min(n,m);
LL ans=0;
for(LL l=1,r;l<=NN;l=r+1){ //N/d 分块
r=NN/(NN/l);
LL d=(l+r)*(r-l+1)/2%mod;
LL re=solve(n/l,m/l);
re=(re+mod)%mod;
ans=(ans+d*re%mod)%mod;
}
printf("%lld\n",ans);
}
}