Lcm

IV.Lcm

既然上一道题中的DZY都能自定义函数,那我们为什么不能呢?

定义\(f(x)\)\(x\)中是否含有平方项。没有则为\(1\),有则为\(0\)。显然,它是积性函数。而我们要求的,就是

\(\sum_{i=1}^n\sum_{j=1}^m\dfrac{ij}{\gcd(i,j)}f(\gcd(i,j))\)

都是老一套了。做多了就发现都是这个德行。

\(\begin{aligned}&\sum_{i=1}^n\sum_{j=1}^m\dfrac{ij}{\gcd(i,j)}f(\gcd(i,j))\\=&\sum_{i=1}^n\sum_{j=1}^m\sum_{d=1}^{\min(n,m)}[\gcd(i,j)=d]\dfrac{ij}{d}f(d)\\=&\sum_{d=1}^{\min(n,m)}\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}dij[\gcd(i,j)=1]f(d)\\=&\sum_{d=1}^{\min(n,m)}f(d)d\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}ij[\gcd(i,j)=1]\\=&\sum_{d=1}^{\min(n,m)}f(d)d\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}ij\sum_{x|i,x|j}\mu(x)\\=&\sum_{d=1}^{\min(n,m)}f(d)d\sum_{x=1}^{\min(n/d,m/d)}x^2\mu(x)\sum_{i=1}^{n/(dx)}\sum_{j=1}^{m/(dx)}ij\end{aligned}\)

我们设\(sum(x)=\dfrac{x(x+1)}{2}\)

\(\begin{aligned}&\sum_{d=1}^{\min(n,m)}f(d)d\sum_{x=1}^{\min(n/d,m/d)}x^2\mu(x)\sum_{i=1}^{n/(dx)}\sum_{j=1}^{m/(dx)}ij\\=&\sum_{d=1}^{\min(n,m)}f(d)d\sum_{x=1}^{\min(n/d,m/d)}x^2\mu(x)sum(\dfrac{n}{dx})sum(\dfrac{m}{dx})\\=&\sum_{T=1}^{\min(n,m)}sum(\dfrac{n}{T})sum(\dfrac{m}{T})\sum_{d|T}f(d)d(\dfrac{T}{d})^2\mu(\dfrac{T}{d})\\=&\sum_{T=1}^{\min(n,m)}sum(\dfrac{n}{T})sum(\dfrac{m}{T})T\sum_{d|T}f(d)(\dfrac{T}{d})\mu(\dfrac{T}{d})\end{aligned}\)

我们设\(g(T)=T\sum_{d|T}f(d)(\dfrac{T}{d})\mu(\dfrac{T}{d})\)。因为\(f\)是积性函数,\(\mu(x)*id(x)\)(注意这里是数乘不是卷积)也是积性函数,因此\(g\)是积性函数。

我们考虑线性筛\(g\)

\(p\)为一质数,则\(g(p)=p*(f(1)*p*\mu(p)+f(p)*1*\mu(1))=p*(1-p)\)

考虑如何求出\(g(xp)\),其中\(p\)为一质数,\(x\)为任意数(保证大于\(p\))。

\(\gcd(x,p)=1\),即\(x,p\)互质时,我们按照积性函数性质,有\(g(xp)=g(x)*g(p)\)

否则,如果\(xp\)中含有三个及以上的因数\(p\),则\(f(xp)=0\),可以直接得出\(g(xp)=0\)

否则,我们将\(xp\)分割成\(p^2\)\(\dfrac{x}{p}\)两个必然互质的部分,运用积性函数性质,则有\(g(xp)=g(\dfrac{x}{p})*g(p^2)\)

考虑如何求出\(g(p^2)\)。按照性质递推,会发现它等于\(-p^3\)

当然咯,为了减少计算量,因为\(g(T)=T\sum_{d|T}f(d)(\dfrac{T}{d})\mu(\dfrac{T}{d})\),因此这个因子\(T\)我们统一留到最后加上。这时,有\(g(p)=(1-p),g(p^2)=-p\)复辟)。

然后就直接整除分块即可。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=4e6;
int n,m,T,pri[N+5],g[N+5],res;
void init(){
	g[1]=1;
	for(int i=2;i<=N;i++){
		if(!pri[i])pri[++pri[0]]=i,g[i]=1-i;
		for(int j=1;j<=pri[0]&&i*pri[j]<=N;j++){
			pri[i*pri[j]]=true;
			if(!(i%pri[j])){
				int r=i/pri[j];
				if(r%pri[j])g[i*pri[j]]=-pri[j]*g[r];
				break;
			}
			g[i*pri[j]]=g[i]*g[pri[j]];
		}
	}
	for(int i=1;i<=N;i++)g[i]=g[i-1]+g[i]*i;
}
int main(){
	scanf("%d",&T),init();
	while(T--){
		scanf("%d%d",&n,&m),res=0;
		for(int l=1,r;l<=min(n,m);l=r+1)r=min(n/(n/l),m/(m/l)),res+=((1ll*(n/l)*(n/l+1)/2)*(1ll*(m/l)*(m/l+1)/2)*(g[r]-g[l-1]));
		printf("%d\n",res&(~((1<<30)|(1<<31))));
	}
	return 0;
}

posted @ 2021-04-05 21:46  Troverld  阅读(202)  评论(0编辑  收藏  举报