HDU 5663 题解

本文详细解析了一个涉及莫比乌斯反演的数学问题,通过巧妙的数学变换,将原问题转化为可高效求解的形式。特别地,文章提供了完整的推导过程及代码实现,展示了如何在限定时间内解决大规模数据问题。

题意简述

(本题时限121212秒,空间512MB512MB512MB,这很大,注意)。有一个女孩问你,给你n,m(n,m&lt;=107)n,m(n,m&lt;=10^7)n,m(n,m<=107),如果你能121212秒内求出∑i=1n∑j=1mf(i,j)\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}f(i,j)i=1nj=1mf(i,j)(其中f(i,j)f(i,j)f(i,j)gcd(i,j)gcd(i,j)gcd(i,j)为平方数时是000,否则是111)。如果你能求出来,她就是你女朋友了QωQQ\omega QQωQ(如果不嫌弃的话珂以找我来当女友。。。我是个珂爱的女孩子呢。。。)

多组数据。数据组数&lt;=104&lt;=10^4<=104

数据

输入
2
1 2333333
10 10
输出
0
33

思路

这个题一看就是一个莫比乌斯反演题。那么,也没什么好说的,开始推式子吧QωQQ\omega QQωQ
首先,能做这个题目的人,肯定会这个式子(这个都不会,下面估计看不懂。。。别急,去我的博客找莫比乌斯反演的那篇,在"LightningUZ の 学习笔记"里有)。
为了方便,设gcd(i,j)=ggcd(i,j)=ggcd(i,j)=g⌊ab⌋=a/b\lfloor\frac{a}{b}\rfloor=a/bba=a/b,并且不妨令n&lt;=mn&lt;=mn<=m。则有:
∑i=1n∑j=1m[g==d]=∑q=1n/dμ(q)(n/q)(m/q)\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[g==d]=\sum\limits_{q=1}^{n/d}\mu(q)(n/q)(m/q)i=1nj=1m[g==d]=q=1n/dμ(q)(n/q)(m/q)
这是十分基础的莫比乌斯反演。

接下来,我们改一下fff的定义,令f(x)=[x∈square]f(x)=[x\in square]f(x)=[xsquare](和题面给出的fff正好相反),那么原式=nm−∑i=1n∑j=1mf(g)=nm-\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}f(g)=nmi=1nj=1mf(g)(求一下补集即可,因为fff反了)。nmnmnm都会求(入门难度),难的就是后面那两个sigmasigmasigma
怎么求呢?首先,我们把ggg放前面枚举,原式
=∑d=1nf(d)∑i=1n∑j=1m[g==d]=\sum\limits_{d=1}^{n}f(d)\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[g==d]=d=1nf(d)i=1nj=1m[g==d]
根据f(d)f(d)f(d)的定义(上面提到了那个重定义),记sqr=sqr=sqr=平方数集合,原式
=∑d∈sqr∑i=1n∑j=1m[g=d]=\sum\limits_{d\in sqr}\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[g=d]=dsqri=1nj=1m[g=d]
=∑d∈sqr∑q=1n/dμ(q)(n/dq)(m/dq)=\sum\limits_{d\in sqr}\sum\limits_{q=1}^{n/d}\mu(q)(n/dq)(m/dq)=dsqrq=1n/dμ(q)(n/dq)(m/dq)
T=dqT=dqT=dq,我们把dddqqq放一块枚举。原式
=∑d∈sqr∑q=1n/dμ(q)(n/T)(m/T)=\sum\limits_{d\in sqr}\sum\limits_{q=1}^{n/d}\mu(q)(n/T)(m/T)=dsqrq=1n/dμ(q)(n/T)(m/T)
=∑T=1n(n/T)(m/T)∑d∈sqr,d∣Tμ(Tk)=\sum\limits_{T=1}^{n}(n/T)(m/T)\sum\limits_{d\in sqr,d|T} \mu(\frac{T}{k})=T=1n(n/T)(m/T)dsqr,dTμ(kT)
这一步就是先枚举了T,然后去后面找哪些q会算到T这一步就是先枚举了T,然后去后面找哪些q会算到TTqT
到这里就结束了??不过说实话,好像还真的没有思路继续下去了。但是我们有一个梦想(做数学题一定要有梦想),我们要是能O(1)O(1)O(1)∑d∈sqr,d∣Tμ(Tk)\sum\limits_{d\in sqr,d|T} \mu(\frac{T}{k})dsqr,dTμ(kT)就好了。(这个式子设为g(T)g(T)g(T)
我们仔细想想,发现,我们只要枚举一个平方数,枚举倍数,加上μ\muμ值,预处理出来,好像真的珂以O(1)O(1)O(1)求!!!
那代码就出来了。
代码:

#include<bits/stdc++.h>
#define N 10010000//时限大+空间大=随便浪
using namespace std;

namespace Flandle_Scarlet//最近喜欢这么写
{
    #define int long long
    int primes[N],mu[N],g[N];
    bool notp[N];
    //g[n]=sigma(d is square and d|n) mu(x/d)
    void Init()//预处理μ和我们推出来珂以预处理的那一部分(设为g(T))
    {
        notp[1]=mu[1]=1;
        int n=10000000;
        int &cnt=primes[0];
        for(int i=2;i<=n;++i)
        {
            if (!notp[i])
            {
                primes[++cnt]=i;
                mu[i]=-1;
            }
            for(int j=1;j<=cnt and i*primes[j]<=n;++j)
            {
                int u=primes[j];
                notp[i*u]=1;
                if (i%u==0)
                {
                    mu[i*u]=0;
                    break;
                }
                else
                {
                    mu[i*u]=-mu[i];
                }
            }
        }//处理好mu

        for(int tmp=1;tmp*tmp<=n;++tmp)
        {
            int d=tmp*tmp;//枚举一个平方数
            for(int j=1;j*d<=n;++j)//j枚举倍数
            {
                g[j*d]+=mu[j];//加上mu[j]
            }
        }
        for(int i=1;i<=n;++i)
        {
            g[i]+=g[i-1];//处理前缀和
        }
    }
    int n,m;
    void Solve()//肥肠水的分块
    {
        if (n>m) n^=m^=n^=m;
        int ans=0;
        for(int l=1,r;l<=n;l=r+1)
        {
            r=min(n/(n/l),m/(m/l));
            ans+=(n/l)*(m/l)*(g[r]-g[l-1]);
        }
        printf("%lld\n",n*m-ans);
    }
    void Main()
    {
        Init();
        int T;
        scanf("%lld",&T);
        while(T--)
        {
            scanf("%lld%lld",&n,&m);
            Solve();
        }
    }
    #undef int//记得undef掉,然后后面就珂以开开心心的int main()了
}
int main()
{
    Flandle_Scarlet::Main();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值