[BZOJ2394/4659]Lcm(莫比乌斯反演)

题目描述

传送门

题解

刚开始有一个非常傻逼的方法
就是画柿子画成了这个样子

T=1ns(nT,mT)p(d)|Tμ(p(d)T)(p(d)T)2p(d)

其中 p(d) 表示第 d 个不含平方因子的数
但是这玩意没法筛,只能暴力求卡时过
但其实这道题还有一种更科学的方法
f(i)=μ(i)2 ,可以发现 f 是一个积性函数
然后假设 n<m ,再画一波柿子
i=1nj=1md=1n[(i,j)=d]ijdf(d)

=d=1ni=1ndj=1md[(i,j)=1]ijdf(d)

利用反演公式 [n=1]=d|nμ(d)
=d=1nt=1ndi=1nd[t|i]ij=1md[t|j]jμ(t)df(d)

s(n,m)=i=1ni+j=1mj
=d=1nt=1nds(ndt,mdt)t2μ(t)df(d)

T=dt ,那么现在 d T 的约数
=T=1ns(nT,mT)d|Tμ(Td)(Td)2df(d)

F(n)=d|nμ(nd)(nd)2df(d),f(d)=df(d),g(n)=d|Tμ(Td)(Td)2
那么 F=g×f 就是一个狄利克雷卷积的形式
可以发现 g f 都是积性函数,那么 F 也是积性函数,用线性筛可以求
比较简单的是当 p 为质数时, F(p)=pp2 ;当 (a,b)=1 时, F(ab)=F(a)F(b)
(a,b)1 时,也就是用 F(a) p 推出 F(ap)
可以发现 a 此时最多含有一个质因子 p ,否则 F(ap)=0
那么我们将 p 先除掉,那么 ap p2 就变成了互质的数
又因为 F(p2)=p3 ,所以 F(ap)=F(ap)(p3)
这样就能求出 F
那么原式
=T=1ns(nT,mT)F(T)

同样分块。。。
时间复杂度 O(n+T(n+m))

代码

#include
#include
#include
#include
#include
#include
using namespace std;
#define Mod 1073741824
#define N 4000005
#define LL long long

int T,n,m,ans;
int p[N],prime[N],mu[N],f[N];

void get(int n)
{
    mu[1]=1;
    for (int i=2;i<=n;++i)
    {
        if (!p[i])
        {
            prime[++prime[0]]=i;
            mu[i]=-1;
        }
        for (int j=1;j<=prime[0]&&i*prime[j]<=n;++j)
        {
            int t=i*prime[j];
            p[t]=1;
            if (i%prime[j]==0)
            {
                mu[t]=0;
                break;
            }
            else mu[t]=-mu[i];
        }
    }
    for (int i=1;i<=n;++i) 
        if (mu[i])
            for (int j=1;j*i<=n;j++) f[j*i]=f[j*i]+mu[j]*j*j*i;
    for (int i=1;i<=n;i++) f[i]=f[i]+f[i-1];
}
int calc(int n,int m)
{
    return (n*(n+1)>>1)*(m*(m+1)>>1);
}
int main()
{
    get(4000000);
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&n,&m);
        if (n>m) swap(n,m);
        ans=0;
        for (int i=1,j=0;i<=n;i=j+1)
        {
            j=min(n/(n/i),m/(m/i));
            ans+=calc(n/i,m/i)*(f[j]-f[i-1]);
        }
        ans=(ans%Mod+Mod)%Mod;
        printf("%d\n",ans);
    }
}
#include
#include
#include
#include
#include
#include
using namespace std;
#define Mod 1073741824
#define N 4000005
#define LL long long

int T,n,m,ans;
int p[N],prime[N],mu[N],f[N],g[N],t[N];

void get(int n)
{
    f[1]=1;
    for (int i=2;i<=n;++i)
    {
        if (!p[i])
        {
            prime[++prime[0]]=i;
            f[i]=i-i*i;
            t[i]=1;
        }
        for (int j=1;j<=prime[0]&&i*prime[j]<=n;++j)
        {
            p[i*prime[j]]=1;
            if (i%prime[j]==0)
            {
                if (t[i]>=2) f[i*prime[j]]=0;
                else
                    f[i*prime[j]]=-f[i/prime[j]]*prime[j]*prime[j]*prime[j];
                t[i*prime[j]]=t[i]+1;
                break;
            }
            else
            {
                f[i*prime[j]]=f[i]*f[prime[j]];
                t[i*prime[j]]=1;
            }
        }
    }
    for (int i=1;i<=n;i++) f[i]=f[i]+f[i-1];
}
int calc(int n,int m)
{
    return (n*(n+1)>>1)*(m*(m+1)>>1);
}
int main()
{
    get(4000000);
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&n,&m);
        if (n>m) swap(n,m);
        ans=0;
        for (int i=1,j=0;i<=n;i=j+1)
        {
            j=min(n/(n/i),m/(m/i));
            ans+=calc(n/i,m/i)*(f[j]-f[i-1]);
        }
        ans=(ans%Mod+Mod)%Mod;
        printf("%d\n",ans);
    }
}

你可能感兴趣的:(题解,莫比乌斯反演)