数论 莫比乌斯反演

前置需求

数论分块

概念

对于一个形如 \(\sum_{x=1}^n \lfloor{\frac{n}{x}}\rfloor\) 的式子,我们发现对于一部分的 \(x\),它们的 \(\lfloor{\frac{n}{x}}\rfloor\) 值相同,因此我们没必要 \(\mathcal{O(n)}\) 计算,可以采用数论分块的办法将这一步的复杂度降低至 \(\mathcal{O(\sqrt{n})}\)。

对于一个已知值 \(n\),给定一个值 \(l\),求一个变量 \(r\) 的最大值使得:\(\lfloor{\frac{n}{l}}\rfloor=\lfloor{\frac{n}{r}}\rfloor\)。比较好得出结论,\(r=\lfloor{\frac{n}{\lfloor{\frac{n}{l}}\rfloor}}\rfloor\)。

证明

摘自 OI-wiki。

应用

在莫反中通常除 \(n\) 外还有一个 \(m\) 形成双层循环,对于它我们只需更改 \(r\) 的位置使得在 \(i\in \left[l,r\right]\) 中 \(\lfloor{\frac{n}{i}}\rfloor\) 与 \(\lfloor{\frac{m}{i}}\rfloor\) 的值始终不变即可。规定 \(n\le m\)。

cpp 复制代码
if(n>m) swap(n,m);
int res=0;
for(int l=1,r;l<=n;l=r+1)
{
	r=min(n/(n/l),m/(m/l));
	res=/*code*/;
}

线性筛

莫反中必用到的知识点之一。

首先了解莫比乌斯函数:

\[\mu(x)=\begin{cases} 1\qquad\quad n=1\\ 0 \qquad\quad n\,含有平方因子\\ (-1)^k\quad k\,为\, n\,本质不同的质因子个数\end{cases}\]

你需要知道的,一是它是一个积性函数,二是怎么线性筛出它。

从定义能看出,\(\mu\) 函数的值跟质数有关,所以在筛它的同时我们还需要线性筛出质数。
最简单的筛

\(u\) 为 \(\mu\) 函数的值,\(N\) 为值域上界,其他的都是筛素数常见的。

cpp 复制代码
int u[N],pri[N],tot;
bool vis[N];
void Wprepare()
{
	u[1]=1;
	for(int i=2;i<=N;i++)
	{
		if(!vis[i]) pri[++tot]=i,u[i]=-1;
		for(int j=1;j<=tot;j++)
		{
			if(i*pri[j]>N) break;
			vis[i*pri[j]]=1;
			if(i%pri[j]==0) break;
			u[i*pri[j]]=-u[i];
		}
	}
}

莫反通常多测,大多数我们需要在准备工作中多预处理一些式子里的其他函数值,有时候还要对其做求前缀和等一系列操作,这些都是因题而异,需要我们灵活应对。

一定的推式子能力

几个显然的很常用的式子转化:

默认 \(n\le m\)

基础一点的:

\[交换律\sum_x\sum\sum f(x)=\sum_x f(x)\sum\sum \]

\[同乘同除,变换上界\sum_{i=1}^n\sum_{j=1}^m [gcd(i,j)=d]=\sum_{i=1}^{\lfloor{\frac{n}{d}}\rfloor}\sum_{j=1}^{\lfloor{\frac{m}{d}}\rfloor}[gcd(i,j)=1] \]

\[等价描述,令\,T=dx:\sum_{d=1}^n\sum_{x=1}^{\lfloor{\frac{n}{d}}\rfloor}=\sum_{T=1}^n \sum_{x|T} \]

提高一点的:

\[综合上面\sum_{i=1}^n \sum_{j=1}^m f(gcd(i,j))=\sum_{d=1}^n f(d)\sum_{i=1}^{\lfloor{\frac{n}{d}}\rfloor} \sum_{j=1}^{\lfloor{\frac{m}{d}}\rfloor} \;[gcd(i,j)=1] \]

\[枚举因数,去循环\sum_{i=1}^n\sum_{j=1}^m\sum_{x|gcd(i,j)} \mu(x)=\sum_{x=1}^n \mu(x)\lfloor{\frac{n}{x}}\rfloor\lfloor{\frac{m}{x}}\rfloor \]

  • 枚举分母,方便数论分块

    令 \(T=dx\)

\[\begin{aligned} Ans &= \sum_{d=1}^n f(d) \sum_{x=1}^{\lfloor{\frac{n}{d}}\rfloor} \mu(x) \lfloor{\frac{n}{dx}}\rfloor \lfloor{\frac{m}{dx}}\rfloor \\ &= \sum_{T=1}^n \lfloor{\frac{n}{T}}\rfloor \lfloor{\frac{m}{T}}\rfloor \sum_{d|T} f(d) \mu(\frac{T}{d}) \end{aligned} \]

主体

由于蒟蒻不会卷积和其他的东西,所以只用到了最基础的一个反演公式

反演公式:

\[[gcd(i,j)=1]=\sum_{d|gcd(i,j)} \mu(d) \]

这是根据莫比乌斯函数的一个性质推出来的:

\[\sum_{d|n}=\begin{cases}1\quad n=1 \\ 0 \quad n\neq 1\end{cases} \]

该性质证明如下:

摘自 OI-wiki。

如果你和我一样对这类式子没有什么太强烈的求知欲,那么食用方法如下:

  • 根据题意,推出式子;
  • 尽可能向 \([gcd(i,j)=1]\) 的方向推,然后使用反演公式;
  • 结合上面的式子转化,推出一个可以预处理出函数值,并能运用数论分块优化复杂度的式子,然后 AC 开始调代码。

例题

做莫反的题我认为关键就在刷题,在不断地推式子中寻找共性,熟能生巧。

先推荐一篇学案,上面的推式子技巧都是循序渐进的,比较好。个人推荐一种学习方式:前几道较基础的题可以看着题解的式子一点一点理解,然后回过头来尝试自己独立完成推式子,再到不断优化筛法。

前几题式子部分会写的详细一点,可能导致篇幅冗长请见谅 qwq。

注:以下题未说明均默认 \(n\le m\)。

YY 的 GCD

这道题虽然在第一题的位置,但要考虑的其实还挺多的,综合了上面几乎所有的推式子技巧。

\[\begin{aligned} Ans&= \sum_{i=1}^n\sum_{j=1}^m \;[gcd(i,j)\in prime] \\ &= \sum_{d=1}^n\sum_{i=1}^n\sum_{j=1}^m \;[gcd(i,j)=d]\;(d\in prime)\\ &= \sum_{d=1}^n\sum_{i=1}^{\lfloor{\frac{n}{d}}\rfloor}\sum_{j=1}^{\lfloor{\frac{m}{d}}\rfloor} \;[gcd(i,j)=1]\;(d\in prime)\\ &=\sum_{d=1}^n\sum_{i=1}^{\lfloor{\frac{n}{d}}\rfloor}\sum_{j=1}^{\lfloor{\frac{m}{d}}\rfloor}\sum_{x|gcd(i,j)}\mu(x)\;(d\in prime)\\&= \sum_{d=1}^n\sum_{x=1}^{\lfloor{\frac{n}{d}}\rfloor}\;\mu(x) \lfloor{\frac{n}{dx}}\rfloor\lfloor{\frac{m}{dx}}\rfloor \;(d\in prime) \end{aligned} \]

令 \(T=dx\),则有:

\[\begin{aligned}Ans&= \sum_{T=1}^n\sum_{d|T} \;\mu(\frac{T}{d})\lfloor{\frac{n}{T}}\rfloor\lfloor{\frac{m}{T}}\rfloor (d\in prime)\\&= \sum_{T=1}^n\;\lfloor{\frac{n}{T}}\rfloor\lfloor{\frac{m}{T}}\rfloor \sum_{d|T} \;\mu(\frac{T}{d})(d\in prime) \end{aligned} \]

发现 \(g(T)= \sum_{d|T} \mu(\frac{T}{d})\) 是可以通过枚举质数的倍数提前处理出来的,对它求前缀和,然后数论分块即可。
点击查看代码

复制代码
#include<bits/stdc++.h>
using namespace std;
const int Ratio=0;
const int N=1e7+5,M=1e7;
int u[N],pri[N],tot,yz[N],g[N];
void Wpre()
{
    u[1]=1;
    for(int i=2;i<=M;i++)
    {
        if(!yz[i]) pri[++tot]=i,u[i]=-1;
        for(int j=1;j<=tot;j++)
        {
            if(i*pri[j]>M) break;
            yz[i*pri[j]]=1;
            if(i%pri[j]==0) break;
            u[i*pri[j]]=-u[i];
        }
    }
    for(int i=1;i<=tot;i++) for(int j=1;j<=M;j++)
    {
        if(pri[i]*j>M) break;
        g[pri[i]*j]+=u[j];
    }
    for(int i=2;i<=M;i++) g[i]+=g[i-1];
}
int main()
{
    Wpre();
    int T,n,m;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        if(n>m) swap(n,m);
        long long res=0;
        for(int l=1,r;l<=n;l=r+1)
            r=min(n/(n/l),m/(m/l)),res+=1ll*(g[r]-g[l-1])*(n/l)*(m/l);
        printf("%lld\n",res);
    }
    return Ratio;
}

约数个数和

个人感觉较简单的一道,要点在于求证 \(d(i,j)=\sum_{x|i}\sum_{y|j}[gcd(x,y)=1]\)
简证

摘自洛谷 Siyuan 的题解。

\[\begin{aligned}Ans&= \sum_{i=1}^n\sum_{j=1}^m\;d(ij)\\&= \sum_{i=1}^n\sum_{j=1}^m\sum_{x|i}\sum_{y|j}\;[gcd(x,y)=1]\\&=\sum_{i=1}^n\sum_{j=1}^m\sum_{x|i}\sum_{y|j}\sum_{d|gcd(x,y)}\mu(d)\\&=\sum_{i=1}^n\sum_{j=1}^m\;\lfloor{\frac{n}{i}}\rfloor\lfloor{\frac{m}{j}}\rfloor\sum_{d|gcd(i,j)}\mu(d)\\&=\sum_{d=1}^n\sum_{i=1}^{\lfloor{\frac{n}{d}}\rfloor}\sum_{j=1}^{\lfloor{\frac{m}{d}}\rfloor}\lfloor{\frac{n}{id}}\rfloor\lfloor{\frac{m}{jd}}\rfloor\mu(d)\\&=\sum_{d=1}^n\;\mu(d)\sum_{i=1}^{\lfloor{\frac{n}{d}}\rfloor}\sum_{j=1}^{\lfloor{\frac{m}{d}}\rfloor} \lfloor{\frac{n}{id}}\rfloor\lfloor{\frac{m}{jd}}\rfloor\\&=\sum_{d=1}^n\;\mu(d)\,(\sum_{i=1}^{\lfloor{\frac{n}{d}}\rfloor}\,\lfloor{\frac{n}{id}}\rfloor)\,(\sum_{j=1}^{\lfloor{\frac{m}{d}}\rfloor}\,\lfloor{\frac{m}{jd}}\rfloor) \end{aligned} \]

后面两坨看着就很熟悉是不是,没错就是数论分块的模板。这道题范围是 \(n\le 5\times10^5\),比较小,所以直接对 \(\mu(d)\) 取前缀和,并 \(\mathcal{O(n\sqrt{n})}\) 预处理出后面 \(g(n)=\sum_{i=1}^n \lfloor{\frac{n}{i}}\rfloor\) 值,再运用数论分块即可,查询复杂度 \(\mathcal{O(T\sqrt{n})}\)。
点击查看代码

复制代码
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int Ratio=0;
const int N=5e4+5,M=5e4;
int u[N],pri[N],tot,yz[N],sum[N];
ll g[N];
void Wpre()
{
    u[1]=1;
    for(int i=2;i<=M;i++)
    {
        if(!yz[i]) pri[++tot]=i,u[i]=-1;
        for(int j=1;j<=tot;j++)
        {
            if(i*pri[j]>M) break;
            yz[i*pri[j]]=1;
            if(i%pri[j]==0) break;
            u[i*pri[j]]=-u[i];
        }
    }
    for(int i=1;i<=M;i++) sum[i]=sum[i-1]+u[i];
    for(int i=1;i<=M;i++)
    {
        ll res=0;
        for(int l=1,r;l<=i;l=r+1)
            r=i/(i/l),res+=1ll*(r-l+1)*(i/l);
        g[i]=res;
    }
}
int main()
{
    Wpre();
    int T,n,m;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        if(n>m) swap(n,m);
        ll res=0;
        for(int l=1,r;l<=n;l=r+1)
            r=min(n/(n/l),m/(m/l)),res+=(sum[r]-sum[l-1])*g[n/l]*g[m/l];
        printf("%lld\n",res);
    }
    return Ratio;
}

数表

都说是板子题,但我打了 天。

按照能把题做下去的思路,我们先不考虑 \(a\) 的限制,设 \(\sigma (x)\) 为 \(x\) 的因数和,那么显然有:

\[\begin{aligned}Ans&=\sum_{i=1}^n\sum_{j=1}^m\;\sigma(gcd(i,j))\\&= \sum_{d=1}^n\sum_{i=1}^n\sum_{j=1}^m \;[gcd(i,j)=d]\;\sigma(d)\\&=\sum_{d=1}^n\sum_{i=1}^{\lfloor{\frac{n}{d}}\rfloor{}}\sum_{j=1}^{\lfloor{\frac{m}{d}}\rfloor{}}\;[gcd(i,j)=1]\;\sigma(d)\\&=\sum_{d=1}^n\sum_{i=1}^{\lfloor{\frac{n}{d}}\rfloor{}}\sum_{j=1}^{\lfloor{\frac{m}{d}}\rfloor{}}\sum_{x|gcd(i,j)}\mu(x)\,\sigma(d)\\&= \sum_{d=1}^n\;\sigma(d)\sum_{x=1}^{\lfloor{\frac{n}{d}}\rfloor{}}\;\mu(x)\lfloor{\frac{n}{dx}}\rfloor{}\lfloor{\frac{m}{dx}}\rfloor{} \end{aligned} \]

令 \(T=dx\),则有:

\[\begin{aligned}Ans&= \sum_{T=1}^n \sum_{d|T} \;\sigma(d)\,\mu(\frac{T}{d})\,\lfloor{\frac{n}{T}}\rfloor{}\lfloor{\frac{m}{T}}\rfloor{}\\&=\sum_{T=1}^n\;\lfloor{\frac{n}{T}}\rfloor{}\lfloor{\frac{m}{T}}\rfloor{}\sum_{d|T}\;\sigma(d)\,\mu(\frac{T}{d}) \end{aligned} \]

不会求 \(\sigma\) 函数的看这里。

化到这一步,后面的部分已经可以提前处理了,此时考虑加入 \(a\) 的限制条件。

g(T)=\\sum_{d\|T} \\sigma(d),\\mu(\\frac{T}{d}) ,当 \(\sigma(d)\le a\) 时会对 \(g(T)\) 产生贡献,而对于所有的多测,改变的只是矩形的规格,并不是数值。。。

那么我们完全可以离线下来做!讲所有询问按 \(a\) 升序排序,每当 \(a\) 的值变大时,对有变动的地方插入相应的值。恰好我们所需的是前缀和且带修,所以考虑用树状数组去维护 \(g(T)\) 函数的前缀和。

插入值的复杂度近似于调和级数,树状数组更新复杂度为 \(\mathcal{O(\log n)}\),故修改总复杂度为 \(\mathcal{O(n\log^2 n)}\);采用数论分块优化查询 \(\mathcal{O(\sqrt{n})}\),树状数组查询 \(\mathcal{O(\log n)}\),故查询总复杂度为 \(\mathcal{O(q\sqrt{n}\log n)}\)。程序总复杂度 \(\mathcal{O(n\log^2 n+q\sqrt{n}\log n)}\)。
点击查看代码

cpp 复制代码
#include<bits/stdc++.h>
#define _(a,b) make_pair(a,b)
#define fi first
#define se second
typedef long long ll;
using namespace std;
const int Ratio=0;
const int N=1e5+5,M=1e5;
int u[N],pri[N],tot,yz[N],low[N];
int ans[N],v[N];
pair<int,int> o[N];
struct rmm{int n,m,a,id;}q[N];
bool cmp(rmm A,rmm B){return A.a<B.a;}
void Wpre()
{
    u[1]=1,o[1]=_(1,1);
    for(int i(2);i<=M;i++)
    {
        if(!yz[i]) pri[++tot]=i,u[i]=-1,low[i]=i+1,o[i]=_(i+1,i);
        for(int j(1);j<=tot;j++)
        {
            if(i*pri[j]>M) break;
            yz[i*pri[j]]=1;
            if(i%pri[j]==0)
            {
                low[i*pri[j]]=low[i]*pri[j]+1;
                o[i*pri[j]]=_(o[i].fi/low[i]*low[i*pri[j]],i*pri[j]);
                break;
            }
            u[i*pri[j]]=-u[i];
            low[i*pri[j]]=pri[j]+1;
            o[i*pri[j]]=_(o[i].fi*o[pri[j]].fi,i*pri[j]);
        }
    }
    sort(o+1,o+M+1);
}
void Wupd(int x,int k){for(;x<=M;x+=(x&-x)) v[x]+=k;}
int Wq(int x)
{
    int res=0;
    while(x) res+=v[x],x-=(x&-x);
    return res;
}
int main()
{
    Wpre();
    int T;scanf("%d",&T);
    for(int i(1);i<=T;i++) scanf("%d%d%d",&q[i].n,&q[i].m,&q[i].a),q[i].id=i;
    sort(q+1,q+1+T,cmp);
    int j=1;
    for(int i(1);i<=T;i++)
    {
        while(j<=M&&o[j].fi<=q[i].a)
        {
            for(int k(o[j].se);k<=M;k+=o[j].se)
                Wupd(k,o[j].fi*u[k/o[j].se]);
            j++;
        }
        int res=0,n=q[i].n,m=q[i].m;
        if(n>m) swap(n,m);
        for(int l(1),r;l<=n;l=r+1)
            r=min(n/(n/l),m/(m/l)),res+=(Wq(r)-Wq(l-1))*(n/l)*(m/l);
        ans[q[i].id]=res;
    }
    for(int i(1);i<=T;i++) printf("%d\n",(ans[i]&(~(1<<31))));
    return Ratio;
}

DZY Loves Math

有新函数,先不管它,推式子。

\[\begin{aligned}Ans&=\sum_{i=1}^n\sum_{j=1}^m \;f(gcd(i,j))\\ &=\sum_{d=1}^n\sum_{i=1}^n\sum_{j=1}^m\;[gcd(i,j)=d] \,f(d)\\&=\sum_{d=1}^n\sum_{i=1}^{\lfloor{\frac{n}{d}}\rfloor{}}\sum_{j=1}^{\lfloor{\frac{m}{d}}\rfloor{}}\;[gcd(i,j)=1]\,f(d)\\&=\sum_{d=1}^n\;f(d)\sum_{i=1}^{\lfloor{\frac{n}{d}}\rfloor{}}\sum_{j=1}^{\lfloor{\frac{m}{d}}\rfloor{}}\sum_{x|gcd(i,j)}\mu(x)\\&=\sum_{d=1}^n\;f(d)\sum_{x=1}^{\lfloor{\frac{n}{d}}\rfloor{}}\;\mu(x)\lfloor{\frac{n}{dx}}\rfloor{}\lfloor{\frac{m}{dx}}\rfloor{} \end{aligned} \]

令 \(T=dx\),则有:

\[\begin{aligned}Ans&=\sum_{T=1}^n\;\lfloor{\frac{n}{T}}\rfloor{}\lfloor{\frac{m}{T}}\rfloor{}\sum_{d|T}\;f(d)\,\mu(\frac{T}{d}) \end{aligned} \]

到这一步似乎就可以做了,不过后面的那坨 g(T)=\\sum_{d\|T}\\ f(d)\\ \\mu(\\frac{T}{d}) 需要调和级数预处理,\(n\le 10^7\),在一个月前的题库上是能跑过的,不过现在不知道为什么速度慢了一半,所以需要我们继续优化,用线性复杂度处理出。

我们着眼于 \(g(T)\) 这个函数。设 \(T\) 共有 \(k\) 个不同的质因子,将其分解为 T=\\prod_{i=1}\^k\\ p_i\^{a_i} 。令 \(T\) 的一个因子 \(d\) 分解为 \(d=\prod_{i=1}^k \;p_i^{b_i}\),发现 \(d\) 有贡献当且仅当 \(\mu(\frac{T}{d})\neq 0\),即 \(\forall i\in[1,k], \;a_i-b_i\le 1\),换句话说 \(b_i\) 的取值只能是 \(a_i\) 或 \(a_i-1\)。

然后再分两种情况:

一种是 \(a_i\) 不全相等的情况,此时必有 存在 \\ i,j\\in\\ \[1,k\],a_i\\lt a_j ,考虑 \(b_i\) 无论取 \(a_i\) 或 \(a_i-1\),不会对 \(f(T)\) 的值产生影响,且两种取法的 \(\mu\) 值之和为 \(0\),即:此时无论如何分配 \(b_i\) 的值,最终结果总能两两分配出相加为 \(0\) 的情况,故 \(g(T)=0\)

另外就是 \(a_i\) 全部相等的情况。此时有贡献的 \(d\) 共有 \(2^k\) 种取值,已知 \(\binom{0}{k}+\binom{2}{k}+\cdots+\binom{2\times \lfloor{\frac{k}{2}}\rfloor{}}{k}=\binom{1}{k}+\binom{3}{k}+\cdots+\binom{2\times \lfloor{\frac{k-1}{2}}\rfloor{}+1}{k}\),即杨辉三角中每行的奇数项和等于偶数项和。括号中上面的数恰好可对应 \(a_i-b_i\) 中值为 \(1\) 的数量,即在 \(f(d)\) 均相同的情况下,\(g(T)\) 的值是 \(0\)。但当括号中上面的数等于 \(k\),即 \(\forall \;i\in[1,k],b_i=a_i-1\) 时,\(f(d)=a_i-1\)。

稍微理解下,然后再来分情况。若 \(k\) 为奇数,则当 \(\forall\;i\in[1,k],b_i=a_i-1\) 时,\(\mu(\frac{T}{d})=(-1)^k=-1\),也就是说,在对结果产生贡献的那一步中本应该减去 \(a_i\),但实际上减去了 \(a_i-1\),那么最终 \(g(T)=1\);若 \(k\) 为偶数同理,此时 \(\mu(\frac{T}{d})=1\),那么本应该加上 \(a_i\),但实际上只加了 \(a_i-1\),最终 \(g(T)=-1\)。

整合一下,发现 \(g\) 函数的取值如下:

\[g(T)=\begin{cases}0\quad\quad\quad\quad 存在 \; i,j\in[1,k],a_i\lt a_j\\ (-1)^{k+1}\quad\, \forall\;i,j\in[1,k],a_i=a_j \end{cases} \]

其中 \(k\) 为 \(T\) 的质因子个数。

实现中,记录最小质因子的指数和它的指数次幂,转移时判断除去最小质因子后次小质因子的指数是否与之相同即可。

预处理 \(g\) 函数及前缀和的复杂度为 \(\mathcal{O(n)}\),数论分块优化后查询复杂度为 \(\mathcal{O(T\sqrt{n})}\),总复杂度 \(\mathcal{O(n+T\sqrt{n})}\)。
点击查看代码

cpp 复制代码
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int Ratio=0;
const int N=1e7+5,M=1e7;
int n,m;
int u[N],pri[N],tot,yz[N],Index[N],low[N],g[N];
void Wpre()
{
    u[1]=1,g[1]=0;
    for(int i(2);i<=M;i++)
    {
        if(!yz[i]) low[i]=pri[++tot]=i,u[i]=-1,Index[i]=g[i]=1;
        for(int j(1);j<=tot;j++)
        {
            if(i*pri[j]>M) break;
            yz[i*pri[j]]=1;
            if(i%pri[j]==0)
            {
                Index[i*pri[j]]=Index[i]+1;
                low[i*pri[j]]=low[i]*pri[j];
                if(low[i]==i) g[i*pri[j]]=1;
                else g[i*pri[j]]=Index[i/low[i]]==Index[i*pri[j]]?-g[i/low[i]]:0;
                break;
            }
            u[i*pri[j]]=-u[i];
            Index[i*pri[j]]=1;
            low[i*pri[j]]=pri[j];
            g[i*pri[j]]=Index[i]==1?-g[i]:0;
        }
    }
    for(int i(2);i<=M;i++) g[i]+=g[i-1];
}
int main()
{
    Wpre();
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        if(n>m) swap(n,m);
        ll res=0;
        for(int l(1),r;l<=n;l=r+1)
            r=min(n/(n/l),m/(m/l)),res+=1ll*(g[r]-g[l-1])*(n/l)*(m/l);
        printf("%lld\n",res);
    }
    return Ratio;
}

其他例题会逐渐更新。

制作不易,如有帮助,请推荐支持,感谢!

相关推荐
Logic1014 小时前
《Mysql数据库应用》 第2版 郭文明 实验1 在MySQL中创建数据库和表核心操作与思路解析
数据库·sql·mysql·学习笔记·计算机网络技术·形考作业·国家开放大学
一马平川的大草原19 小时前
AI Agent常见问题和核心术语
人工智能·学习笔记·agent
Logic1012 天前
《Mysql数据库应用》 第2版 郭文明 实验6 数据库系统维护核心操作与思路解析
数据库·sql·mysql·学习笔记·计算机网络技术·形考作业·国家开放大学
Logic1012 天前
《数据库运维》 郭文明 实验4 数据库备份与恢复实验核心操作与思路解析
运维·数据库·sql·mysql·学习笔记·形考作业·国家开放大学
Logic1012 天前
《数据库运维》 郭文明 实验2 MySQL数据库对象管理核心操作与思路解析
运维·数据库·mysql·学习笔记·计算机网络技术·形考作业·国家开放大学
Logic1013 天前
一份系统化《Python爬虫教程》学习笔记:Python爬虫63个核心案例精讲(含反爬策略与源码剖析)
经验分享·爬虫·python·学习笔记·编程·软件开发
Logic1014 天前
《Mysql数据库应用》 第2版 郭文明 实验4 视图和索引的构建与使用核心操作与思路解析
数据库·sql·mysql·学习笔记·计算机网络技术·形考作业·国家开放大学
Johnny_le5 天前
生物化学Learning Track(28)脂肪酸代谢
学习笔记·生物化学
Logic1015 天前
《Mysql数据库应用》 第2版 郭文明 实验2 数据查询操作核心操作与思路解析
数据库·sql·mysql·学习笔记·计算机网络技术·形考作业·国家开放大学
四谎真好看6 天前
MySQL学习笔记(基础篇1)
笔记·学习·mysql·学习笔记