[BZOJ2154]Crash的数字表格(莫比乌斯反演)

Address

https://www.lydsy.com/JudgeOnline/problem.php?id=2154

Solution

显然是莫比乌斯反演

i=1Nj=1Mlcm(i,j) ∑ i = 1 N ∑ j = 1 M lcm ( i , j )

=i=1Nj=1Mijgcd(i,j) = ∑ i = 1 N ∑ j = 1 M i j gcd ( i , j )

di=1Nj=1Mijd[gcd(i,j)=d] ∑ d ∑ i = 1 N ∑ j = 1 M i j d [ gcd ( i , j ) = d ]

=di=1Ndj=1Mddij[gcd(i,j)=1] = ∑ d ∑ i = 1 ⌊ N d ⌋ ∑ j = 1 ⌊ M d ⌋ d i j [ gcd ( i , j ) = 1 ]

=ddi=1Ndj=1Mdijk|gcd(i,j)μ(k) = ∑ d d ∑ i = 1 ⌊ N d ⌋ ∑ j = 1 ⌊ M d ⌋ i j ∑ k | gcd ( i , j ) μ ( k )

=ddki=1,k|iNdj=1,k|jMdijμ(k) = ∑ d d ∑ k ∑ i = 1 , k | i ⌊ N d ⌋ ∑ j = 1 , k | j ⌊ M d ⌋ i j μ ( k )

=ddkk2S(Ndk)S(Mdk)μ(k) = ∑ d d ∑ k k 2 S ( ⌊ N d k ⌋ ) S ( ⌊ M d k ⌋ ) μ ( k )

其中 S(x)=x(x+1)2 S ( x ) = x ( x + 1 ) 2
发现下取整内的分母是乘积的形式,还是不好做。
所以设 T=dk T = d k
Tk|TTkk2S(NT)S(MT)μ(k) ∑ T ∑ k | T T k k 2 S ( ⌊ N T ⌋ ) S ( ⌊ M T ⌋ ) μ ( k )

=TTS(NT)S(MT)k|Tkμ(k) = ∑ T T S ( ⌊ N T ⌋ ) S ( ⌊ M T ⌋ ) ∑ k | T k μ ( k )

再考虑求 f(T)=k|Tkμ(k) f ( T ) = ∑ k | T k μ ( k )
对于任意的 gcd(S,T)=1 gcd ( S , T ) = 1 ,都有:
f(ST)=k|STkμ(k) f ( S T ) = ∑ k | S T k μ ( k )

d|Sk|Tdkμ(dk) ∑ d | S ∑ k | T d k μ ( d k )

=(d|Sμ(d))(k|Tμ(k)) = ( ∑ d | S μ ( d ) ) ( ∑ k | T μ ( k ) )

=f(S)f(T) = f ( S ) f ( T )

我们得到: f f 是积性函数。可以线性筛求。
f(1)=1

nk1,f(nk)=1n ∀ n 为 质 数 且 k ≥ 1 , f ( n k ) = 1 − n

mm|n,f(nm)=f(n) ∀ m 为 质 数 且 m | n , f ( n m ) = f ( n )

gcd(n,m)=1,f(nm)=f(n)f(m) ∀ gcd ( n , m ) = 1 , f ( n m ) = f ( n ) f ( m )

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
#define Step(i, a, b, x) for (i = a; i <= b; i += x)
using namespace std;
const int MaxN = 1e7, N = 1e7 + 5, ZZQ = 20101009;
int n, m, tot, pri[N], zzq[N], ans;
bool mark[N];
void sieve() {
    int i, j;
    mark[0] = mark[zzq[1] = 1] = 1;
    For (i, 2, MaxN) {
        if (!mark[i]) zzq[pri[++tot] = i] = 1 - i + ZZQ;
        For (j, 1, tot) {
            if (1ll * i * pri[j] > MaxN) break;
            mark[i * pri[j]] = 1;
            if (i % pri[j] == 0) {
                zzq[i * pri[j]] = zzq[i];
                break;
            }
            else zzq[i * pri[j]] = 1ll * zzq[i] * zzq[pri[j]] % ZZQ;
        }
    }
}
int S(int n) {
    return (1ll * n * (n + 1) >> 1) % ZZQ;
}
int main() {
    int i;
    cin >> n >> m;
    sieve();
    For (i, 1, min(n, m))
        ans = (ans + 1ll * i * S(n / i) % ZZQ * S(m / i)
        % ZZQ * zzq[i] % ZZQ) % ZZQ;
    cout << ans << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值