BZOJ2154 Crash的数字表格

原题链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2154

Crash的数字表格

Description

今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple)。对于两个正整数a和b,LCM(a, b)表示能同时被a和b整除的最小正整数。例如,LCM(6, 8) = 24。回到家后,Crash还在想着课上学的东西,为了研究最小公倍数,他画了一张N*M的表格。每个格子里写了一个数字,其中第i行第j列的那个格子里写着数为LCM(i, j)。一个4*5的表格如下: 1 2 3 4 5 2 2 6 4 10 3 6 3 12 15 4 4 12 4 20 看着这个表格,Crash想到了很多可以思考的问题。不过他最想解决的问题却是一个十分简单的问题:这个表格中所有数的和是多少。当N和M很大时,Crash就束手无策了,因此他找到了聪明的你用程序帮他解决这个问题。由于最终结果可能会很大,Crash只想知道表格里所有数的和mod 20101009的值。

Input

输入的第一行包含两个正整数,分别表示N和M。

Output

输出一个正整数,表示表格中所有数的和mod 20101009的值。

Sample Input

4 5

Sample Output

122

【数据规模和约定】

100%的数据满足N, M ≤ 10^7。

题解

初始式子:

ans=i=1nj=1mlcm(i,j) a n s = ∑ i = 1 n ∑ j = 1 m l c m ( i , j )

显然有 lcm(a,b)=abgcd(a,b) l c m ( a , b ) = a b g c d ( a , b )

i=1nj=1mijgcd(i,j) ∑ i = 1 n ∑ j = 1 m i j g c d ( i , j )

基本操作之更该枚举项+提取公因数:

i=1nj=1mijgcd(i,j)=d=1min(n,m)i=1nj=1mijd[d=gcd(i,j)]=d=1min(n,m)d2i=1ndj=1mdijd[1=gcd(i,j)]=d=1min(n,m)di=1ndj=1mdij[1=gcd(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 [ d = g c d ( i , j ) ] = ∑ d = 1 m i n ( n , m ) d 2 ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j d [ 1 = g c d ( i , j ) ] = ∑ d = 1 m i n ( n , m ) d ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j [ 1 = g c d ( i , j ) ]

我们把 ndi=1mdj=1ij[1=gcd(i,j)] ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j [ 1 = g c d ( i , j ) ] 提出来单独调♂教,设 F(x,y)=xi=1yj=1ij[1=gcd(i,j)] F ( x , y ) = ∑ i = 1 x ∑ j = 1 y i j [ 1 = g c d ( i , j ) ]

F(x,y)=i=1xj=1yij[1=gcd(i,j)]=i=1xj=1yijd|gcd(i,j)μ(d)=d=1min(x,y)μ(d)i=1xj=1yij[d|gcd(i,j)]=d=1min(x,y)μ(d)d2i=1xdj=1ydij=d=1min(x,y)μ(d)d2i=1xdij=1ydj=d=1min(x,y)μ(d)d2(1+xd)xd2(1+yd)yd2 F ( x , y ) = ∑ i = 1 x ∑ j = 1 y i j [ 1 = g c d ( i , j ) ] = ∑ i = 1 x ∑ j = 1 y i j ∑ d | g c d ( i , j ) μ ( d ) = ∑ d = 1 m i n ( x , y ) μ ( d ) ∑ i = 1 x ∑ j = 1 y i j [ d | g c d ( i , j ) ] = ∑ d = 1 m i n ( x , y ) μ ( d ) d 2 ∑ i = 1 ⌊ x d ⌋ ∑ j = 1 ⌊ y d ⌋ i j = ∑ d = 1 m i n ( x , y ) μ ( d ) d 2 ∑ i = 1 ⌊ x d ⌋ i ∑ j = 1 ⌊ y d ⌋ j = ∑ d = 1 m i n ( x , y ) μ ( d ) d 2 ( 1 + ⌊ x d ⌋ ) ⌊ x d ⌋ 2 ( 1 + ⌊ y d ⌋ ) ⌊ y d ⌋ 2

代回原式:

d=1min(n,m)d×F(nd,md)=d=1min(n,m)dd=1min(n,m)dμ(d)d2(1+xdd)xdd2(1+ydd)ydd2 ∑ d = 1 m i n ( n , m ) d × F ( ⌊ n d ⌋ , ⌊ m d ⌋ ) = ∑ d = 1 m i n ( n , m ) d ∑ d ′ = 1 ⌊ m i n ( n , m ) d ⌋ μ ( d ′ ) d ′ 2 ( 1 + ⌊ x d d ′ ⌋ ) ⌊ x d d ′ ⌋ 2 ( 1 + ⌊ y d d ′ ⌋ ) ⌊ y d d ′ ⌋ 2

自然想到将 dd d d ′ 替换为 T T 并枚举T

=T=1min(n,m)(1+xT)xT2(1+yT)yT2Td|Tμ(d)d = ∑ T = 1 m i n ( n , m ) ( 1 + ⌊ x T ⌋ ) ⌊ x T ⌋ 2 ( 1 + ⌊ y T ⌋ ) ⌊ y T ⌋ 2 T ∑ d ′ | T μ ( d ′ ) d ′

T=i×p[j],f(T)=Td|Tμ(d)d,g(T)=d|Tμ(d)d T = i × p [ j ] , f ( T ) = T ∑ d ′ | T μ ( d ′ ) d ′ , g ( T ) = ∑ d ′ | T μ ( d ′ ) d ′ ,我们单独拿出 g(T) g ( T ) 讨论如何线筛:

1.当 T T 为素数时,d的取值只能为 1,T 1 , T ,此时 g(T)=1T g ( T ) = 1 − T

2.当 T T 拥有多个最小质因子时,由于没有新增质因子,所以不影响我们的枚举,此时g(T)=g(i)

3.当 T T 的最小质因子只有一个时,在原来枚举的所有因数的基础上,我们还多了一堆“原来的因数×p[j]”,因为多了一个质因数之后, μ(d×p[j])=μ(d) μ ( d ′ × p [ j ] ) = − μ ( d ′ ) ,所以这个最小质因子的贡献为 p[j]×g(i) − p [ j ] × g ( i ) ,此时 g(T)=g(i)×(1p[j]) g ( T ) = g ( i ) × ( 1 − p [ j ] )

在筛完 g(T) g ( T ) 后,依次乘以 T T 即可得到f(T)

代码实现时,对 f(T) f ( T ) 求前缀和,套上下底分块即可实现 O(n) O ( n ) 求解。

代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int M=1e7+5,mod=20101009;
int n,m,p[M/3];
ll f[M],ans,s1,s2;
bool isp[M];
void pre()
{
    f[1]=1;int t;
    for(int i=2;i<=n;++i)
    {
        if(!isp[i])p[++p[0]]=i,f[i]=1-i;
        for(int j=1;j<=p[0];++j)
        {
            t=i*p[j];if(t>n)break;
            isp[t]=1;
            if(i%p[j]==0){f[t]=f[i];break;}
            f[t]=f[i]*(1-p[j]);
        }
        f[i]=(f[i-1]+f[i]*i%mod)%mod;
    }
}
void in(){scanf("%d%d",&n,&m);}
void ac()
{
    if(n>m)swap(n,m);pre();
    for(int l=1,r;l<=n;l=r+1)
    {r=min(n/(n/l),m/(m/l));s1=1ll*(1+n/l)*(n/l)/2%mod;s2=1ll*(1+m/l)*(m/l)/2%mod;(ans+=(f[r]-f[l-1])*((s1*s2)%mod)%mod)%=mod;}
    printf("%lld",(ans+mod)%mod);
}
int main(){in();ac();}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值