【jzoj1938】【2011集训队出题】【Crash的数字表格】【莫比乌斯反演】

56 篇文章 0 订阅

题目大意

Ans=Nx=1My=1Lcm(x,y)

解题思路

Ans=Nx=1My=1Lcm(x,y)
=Nx=1My=1xy/Gcd(x,y)
=Nd=11/dNx=1My=1xy[Gcd(x,y)==d] 默认N<=M
g[d]=Nx=1My=1xy[Gcd(x,y)==d]
f[d]=Nx=1My=1xy[d|Gcd(x,y)]=d2(1+N/d)N/d(1+M/d)M/d/4=N/di=1g[di]
根据莫比乌斯反演
g[d]=N/di=1f[di]mu(i)
=N/di=1d2i2(1+N/di)N/di(1+M/di)M/di/4mu(i)
Ans=Nd=11/dN/di=1d2i2(1+N/di)N/di(1+M/di)M/di/4mu(i)
令T=id
=NT=1T(1+N/T)N/T(1+M/T)M/T/4i|Tmu(i)i
由莫比乌斯函数性质得 h[i]=i|Tmu(i)i 是积性函数, h[x]=pi1pi 可以用线筛求。
对于前一部分可以分块求,对于后一部分可以前缀和求。
前面的T其实可以放进后面求。

code

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LF double
#define LL long long
#define Min(a,b) ((a<b)?a:b)
#define Max(a,b) ((a>b)?a:b)
#define Fo(i,j,k) for(int i=j;i<=k;i++)
#define Fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
int const Mxn=1e7,Mo=20101009;
int N,M,F[Mxn+9],Pri[Mxn+9];
int main(){
    freopen("d.in","r",stdin);
    freopen("d.out","w ",stdout);
    scanf("%d%d",&N,&M);
    if(N>M)swap(N,M);
    F[1]=1;
    Fo(i,2,N){
        if(!F[i])Pri[++Pri[0]]=i,F[i]=1-i;
        Fo(j,1,Pri[0]){
            if(i*Pri[j]>N)break;
            if(i%Pri[j]==0){F[i*Pri[j]]=F[i];break;}
            else F[i*Pri[j]]=F[i]*(1-Pri[j]);
        }
        F[i]=(1ll*F[i]*i+F[i-1])%Mo;
    }
    int Ans=0;
    for(int i=1,j,Ni,Mi;i<=N;i=j+1){
        Ni=N/i;Mi=M/i;
        j=Min(N/(Ni),M/(Mi));
        Ans=(Ans+((1ll+Ni)*Ni/2%Mo)*((1ll+Mi)*Mi/2%Mo)%Mo
            %Mo*(F[j]-F[i-1])%Mo)%Mo;
    }
    printf("%d",(Ans+Mo)%Mo);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值