令 \(s(n)=\frac{n(n+1)}{2}\)
\[\sum_{T=1}^{\min(n,m)}T^2 s(\lfloor \frac{n}{T} \rfloor)s(\lfloor \frac{m}{T} \rfloor)\sum_{k|T}k\mu^2(k) \mu(\frac{T}{k}) \]令 \(f(n)=\sum_{d|n} d\mu^2(d) \mu(\frac{n}{d})\)
\[\sum_{T=1}^{\min(n,m)}T^2 f(T)s(\lfloor \frac{n}{T} \rfloor)s(\lfloor \frac{m}{T} \rfloor) \]首先由狄利克雷卷积的性质,\(f(n)\) 是一个积性函数,考虑线性筛。
首先如果 \(n\) 的质因子数量出现 \(3\) 次以上,那么 \(d\) 和 \(\frac{n}{d}\) 一定有一个有平方因子,\(\mu\) 为 \(0\)。
那么每个质因子只能出现 \(1\) 次或 \(2\) 次。
\[f(p)=1\mu^2(1) \mu(p)+p\mu^2(p)\mu(1)=p-1 \] \[f(p^2)=1\mu^2(1) \mu(p^2)+p\mu^2(p)\mu(p)+p^2\mu^2(p^2)\mu(1)=-p \]\(f(1)=1\) ,线筛后乘上 \(i^2\) 做前缀和就可以整除分块。
#include <cstdio>
#include <iostream>
using namespace std;
const int MAXN = 1e6 , Mod = 1e9 + 7;
int prn , prime[ MAXN + 5 ] , f[ MAXN + 5 ];
bool vis[ MAXN + 5 ];
void sieve( ) {
f[ 1 ] = 1;
for( int i = 2 ; i <= MAXN ; i ++ ) {
if( !vis[ i ] ) { prime[ ++ prn ] = i , f[ i ] = i - 1; }
for( int j = 1 ; j <= prn && 1ll * i * prime[ j ] <= MAXN ; j ++ ) {
vis[ i * prime[ j ] ] = 1;
if( i % prime[ j ] == 0 ) {
if( ( i / prime[ j ] ) % prime[ j ] ) f[ i * prime[ j ] ] = 1ll * f[ i / prime[ j ] ] * ( Mod - prime[ j ] ) % Mod;
break;
}
f[ i * prime[ j ] ] = 1ll * f[ i ] * f[ prime[ j ] ] % Mod;
}
}
for( int i = 1 ; i <= MAXN ; i ++ ) f[ i ] = ( f[ i - 1 ] + 1ll * f[ i ] * i % Mod * i % Mod ) % Mod;
}
int Sum1( int n ) {
return 1ll * n * ( n + 1 ) / 2 % Mod;
}
int Solve( int n , int m ) {
int k = min( n , m ) , Ans = 0;
for( int l = 1 , r ; l <= k ; l = r + 1 ) {
r = min( n / ( n / l ) , m / ( m / l ) );
Ans = ( Ans + 1ll * ( f[ r ] - f[ l - 1 ] + Mod ) % Mod * Sum1( n / l ) % Mod * Sum1( m / l ) % Mod ) % Mod;
}
return Ans;
}
int t , n , m;
int main( ) {
sieve( );
scanf("%d",&t);
for( int i = 1 ; i <= t ; i ++ ) {
scanf("%d %d",&n,&m);
printf("%d\n", Solve( n , m ) );
}
return 0;
}