SP26108 TRENDGCD - Trending GCD

\[\sum_{i=1}^n\sum_{j=1}^m ij \gcd(i,j)\mu^2(\gcd(i,j)) \]

\[\sum_{k=1}^{\min(n,m)}\sum_{i=1}^n\sum_{j=1}^m [\gcd(i,j)=k]ij k\mu^2(k) \]

\[\sum_{k=1}^{\min(n,m)}k^3\mu^2(k)\sum_{i=1}^{\lfloor \frac{n}{k} \rfloor}\sum_{j=1}^{{\lfloor \frac{m}{k} \rfloor}} [\gcd(i,j)=1]ij \]

\[\sum_{k=1}^{\min(n,m)}k^3\mu^2(k) \sum_{d=1}^{\min(\lfloor \frac{n}{k} \rfloor,\lfloor \frac{m}{k} \rfloor)}\mu(d)d^2\sum_{i=1}^{\lfloor \frac{n}{kd} \rfloor}\sum_{j=1}^{{\lfloor \frac{m}{kd} \rfloor}} ij \]

\[\sum_{k=1}^{\min(n,m)}\sum_{dk=1}^{\min(n,m)}k^3\mu^2(k) \mu(d)d^2\sum_{i=1}^{\lfloor \frac{n}{kd} \rfloor}\sum_{j=1}^{{\lfloor \frac{m}{kd} \rfloor}} ij \]

\(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;
}
posted @ 2021-04-08 20:51  chihik  阅读(36)  评论(0编辑  收藏  举报