P1829 [国家集训队]Crash的数字表格(莫比乌斯反演+数论分块)

题意:

给 定 n , m , 要 求 计 算 ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) 给定n,m,要求计算\sum_{i=1}^n\sum_{j=1}^mlcm(i,j) n,m,i=1nj=1mlcm(i,j)

答 案 对 20101009 取 模 答案对20101009取模 20101009

数据范围:n,m<=1e7

解法:

a n s = ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) = ∑ i = 1 n ∑ j = 1 m i ∗ j g c d ( i , j ) = ∑ d = 1 m i n ( n , m ) ∑ i = 1 n ∑ j = 1 m i ∗ j d [ g c d ( i , j ) = d ] = ∑ d = 1 m i n ( n , m ) ∑ i = 1 n ∑ j = 1 m i d ∗ j d ∗ d ∗ [ g c d ( i , j ) = d ] = ∑ d = 1 m i n ( n , m ) d ∑ i = 1 n ∑ j = 1 m i d ∗ j d ∗ [ g c d ( i , j ) = d ] = ∑ d = 1 m i n ( n , m ) d ∑ i = 1 n / d ∑ j = 1 m / d i ∗ j ∗ [ g c d ( i , j ) = 1 ] 设 f ( n , m ) = ∑ i = 1 n ∑ j = 1 m i ∗ j ∗ [ g c d ( i , j ) = 1 ] 存 在 反 演 结 论 : [ g c d ( i , j ) = 1 ] = ∑ d ∣ g c d ( i , j ) μ ( d ) 因 此 f ( n , m ) = ∑ i = 1 n ∑ j = 1 m i ∗ j ∑ d ∣ g c d ( i , j ) μ ( d ) = ∑ d = 1 m i n ( n , m ) μ ( d ) ∑ d ∣ i , i < = n ∑ d ∣ j , j < = m i ∗ j = ∑ d = 1 m i n ( n , m ) μ ( d ) ∑ i = 1 n / d ∑ j = 1 m / d ( i ∗ d ) ∗ ( j ∗ d ) = ∑ d = 1 m i n ( n , m ) μ ( d ) d 2 ∑ i = 1 n / d ∑ j = 1 m / d i ∗ j 设 s ( i ) = i ∗ ( i + 1 ) 2 那 么 f ( n , m ) = ∑ d = 1 m i n ( n , m ) μ ( d ) d 2 s ( n d ) s ( m d ) f ( n , m ) 可 以 数 论 分 块 优 化 到 O ( n ) 继 续 之 前 对 a n s 的 推 导 : a n s = ∑ d = 1 m i n ( n , m ) d ∑ i = 1 n / d ∑ j = 1 m / d i ∗ j ∗ [ g c d ( i , j ) = 1 ] = ∑ d = 1 m i n ( n , m ) d ∗ f ( n d , m d ) 可 以 用 数 论 分 块 优 化 到 O ( n ) 由 于 里 面 还 套 了 一 个 f ( n , m ) 的 O ( n ) 所 以 总 复 杂 度 为 O ( n ∗ n ) = O ( n ) ans=\sum_{i=1}^n\sum_{j=1}^mlcm(i,j)\\ =\sum_{i=1}^n\sum_{j=1}^m \frac{i*j}{gcd(i,j)}\\ =\sum_{d=1}^{min(n,m)}\sum_{i=1}^n\sum_{j=1}^m\frac{i*j}{d}[gcd(i,j)=d]\\ =\sum_{d=1}^{min(n,m)}\sum_{i=1}^n\sum_{j=1}^m\frac{i}{d}*\frac{j}{d}*d*[gcd(i,j)=d]\\ =\sum_{d=1}^{min(n,m)}d\sum_{i=1}^n\sum_{j=1}^m\frac{i}{d}*\frac{j}{d}*[gcd(i,j)=d]\\ =\sum_{d=1}^{min(n,m)}d\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}i*j*[gcd(i,j)=1]\\ 设f(n,m)=\sum_{i=1}^n\sum_{j=1}^mi*j*[gcd(i,j)=1]\\ 存在反演结论:[gcd(i,j)=1]=\sum_{d|gcd(i,j)}\mu(d)\\ 因此f(n,m)=\sum_{i=1}^n\sum_{j=1}^mi*j\sum_{d|gcd(i,j)}\mu(d)\\ =\sum_{d=1}^{min(n,m)}\mu(d)\sum_{d|i,i<=n}\sum_{d|j,j<=m}i*j\\ =\sum_{d=1}^{min(n,m)}\mu(d)\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}(i*d)*(j*d)\\ =\sum_{d=1}^{min(n,m)}\mu(d)d^2\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}i*j\\ 设s(i)=\frac{i*(i+1)}{2}\\ 那么f(n,m)=\sum_{d=1}^{min(n,m)}\mu(d)d^2s(\frac{n}{d})s(\frac{m}{d})\\ f(n,m)可以数论分块优化到O(\sqrt n)\\ 继续之前对ans的推导:\\ ans=\sum_{d=1}^{min(n,m)}d\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}i*j*[gcd(i,j)=1]\\ =\sum_{d=1}^{min(n,m)}d*f(\frac{n}{d},\frac{m}{d})\\ 可以用数论分块优化到O(\sqrt n)\\ 由于里面还套了一个f(n,m)的O(\sqrt n)\\ 所以总复杂度为O(\sqrt n*\sqrt n)=O(n) ans=i=1nj=1mlcm(i,j)=i=1nj=1mgcd(i,j)ij=d=1min(n,m)i=1nj=1mdij[gcd(i,j)=d]=d=1min(n,m)i=1nj=1mdidjd[gcd(i,j)=d]=d=1min(n,m)di=1nj=1mdidj[gcd(i,j)=d]=d=1min(n,m)di=1n/dj=1m/dij[gcd(i,j)=1]f(n,m)=i=1nj=1mij[gcd(i,j)=1]:[gcd(i,j)=1]=dgcd(i,j)μ(d)f(n,m)=i=1nj=1mijdgcd(i,j)μ(d)=d=1min(n,m)μ(d)di,i<=ndj,j<=mij=d=1min(n,m)μ(d)i=1n/dj=1m/d(id)(jd)=d=1min(n,m)μ(d)d2i=1n/dj=1m/dijs(i)=2i(i+1)f(n,m)=d=1min(n,m)μ(d)d2s(dn)s(dm)f(n,m)O(n )ans:ans=d=1min(n,m)di=1n/dj=1m/dij[gcd(i,j)=1]=d=1min(n,m)df(dn,dm)O(n )f(n,m)O(n )O(n n )=O(n)

code:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxm=1e7+5;
const int mod=20101009;
int p[maxm],c;
int np[maxm];
int mu[maxm];
int sum[maxm];
int n,m;
void init(){
    mu[1]=1;
    for(int i=2;i<maxm;i++){
        if(!np[i])p[c++]=i,mu[i]=-1;
        for(int j=0;j<c;j++){
            if(p[j]*i>=maxm)break;
            np[p[j]*i]=1;
            mu[p[j]*i]=(i%p[j]?-mu[i]:0);
            if(i%p[j]==0)break;
        }
    }
    for(int i=1;i<maxm;i++){
        sum[i]=(sum[i-1]+mu[i]*i*i%mod)%mod;
    }
}
int s(int x){
    return x*(x+1)/2%mod;
}
int f(int n,int m){
    int mi=min(n,m);
    int ans=0;
    for(int l=1,r;l<=mi;l=r+1){
        r=min(n/(n/l),m/(m/l));
        ans+=s(n/l)*s(m/l)%mod*(sum[r]-sum[l-1])%mod;
        ans%=mod;
    }
    return ans;
}
signed main(){
    ios::sync_with_stdio(0);
    init();
    cin>>n>>m;
    int mi=min(n,m);
    int ans=0;
    for(int l=1,r;l<=mi;l=r+1){
        r=min(n/(n/l),m/(m/l));
        ans+=(s(r)-s(l-1))%mod*f(n/l,m/l)%mod;
        ans%=mod;
    }
    ans=(ans%mod+mod)%mod;
    cout<<ans<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值