2019.01.21【BZOJ2694】【BZOJ4659】Lcm(莫比乌斯反演)

DarkBZOJ传送门

BZOJ传送门


解析:

首先这个东西我们必须要把它转化成式子不然没法推。

考虑利用莫比乌斯函数转化一下,我们要求的就是:
∑ i = 1 n ∑ j = 1 m l c m ( i , j ) ∣ μ ( g c d ( i , j ) ) ∣ \sum_{i=1}^n\sum_{j=1}^mlcm(i,j)|\mu(gcd(i,j))| i=1nj=1mlcm(i,j)μ(gcd(i,j))

注意上面 μ \mu μ外面套的是绝对值符号。

我必须承认这个式子看着很鬼畜,但是只要不怕转化,就能化出来: A n s = ∑ i = 1 n ∑ j = 1 m i j g c d ( i , j ) ∣ μ ( g c d ( i , j ) ) ∣ = ∑ d = 1 min ⁡ ( n , m ) ∑ i = 1 n ∑ j = 1 m i j d ∣ μ ( d ) ∣ [ g c d ( i , j ) = d ] = ∑ d = 1 min ⁡ ( n , m ) d ∣ μ ( d ) ∣ ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j [ g c d ( i , j ) = 1 ] \begin{aligned} Ans=&\sum_{i=1}^n\sum_{j=1}^m\frac{ij}{gcd(i,j)}|\mu(gcd(i,j))|\\ =&\sum_{d=1}^{\min(n,m)}\sum_{i=1}^n\sum_{j=1}^m\frac{ij}d|\mu(d)|[gcd(i,j)=d]\\ =&\sum_{d=1}^{\min(n,m)}d|\mu(d)|\sum_{i=1}^{\lfloor\frac{n}d\rfloor}\sum_{j=1}^{\lfloor\frac{m}d\rfloor}ij[gcd(i,j)=1] \end{aligned} Ans===i=1nj=1mgcd(i,j)ijμ(gcd(i,j))d=1min(n,m)i=1nj=1mdijμ(d)[gcd(i,j)=d]d=1min(n,m)dμ(d)i=1dnj=1dmij[gcd(i,j)=1]

当出现形如 [ n = 1 ] [n=1] [n=1]的求和式子的时候,我们知道,可以开始反演了:
A n s = ∑ d = 1 min ⁡ ( n , m ) d ∣ μ ( d ) ∣ ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ i j ∑ t ∣ g c d ( i , j ) μ ( t ) \begin{aligned} Ans=&\sum_{d=1}^{\min(n,m)}d|\mu(d)|\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}ij\sum_{t\mid gcd(i,j)}\mu(t) \end{aligned} Ans=d=1min(n,m)dμ(d)i=1dnj=1dmijtgcd(i,j)μ(t)

接下来用 S ( n ) S(n) S(n)来表示 ∑ i = 1 n i \sum_{i=1}^ni i=1ni,显然上面的 i j ij ij用结合律拆开后可以简化。得到: A n s = ∑ d = 1 min ⁡ ( n , m ) d ∣ μ ( d ) ∣   S ( ⌊ n d ⌋ ) S ( ⌊ m d ⌋ ) ∑ t ∣ g c d ( i , j ) , i ≤ ⌊ n d ⌋ , j ≤ ⌊ m d ⌋ μ ( t ) = ∑ d = 1 min ⁡ ( n , m ) d ∣ μ ( d ) ∣ ∑ t = 1 min ⁡ ( n , m ) d t 2 μ ( t ) S ( ⌊ n d t ⌋ ) S ( ⌊ m d t ⌋ ) \begin{aligned} Ans=&\sum_{d=1}^{\min(n,m)}d|\mu(d)|\,S(\lfloor\frac{n}d\rfloor)S(\lfloor\frac{m}d\rfloor)\sum_{t\mid gcd(i,j),i\leq \lfloor\frac{n}d\rfloor,j\leq \lfloor\frac{m}{d}\rfloor}\mu(t)\\ =&\sum_{d=1}^{\min(n,m)}d|\mu(d)|\sum_{t=1}^{\frac{\min(n,m)}{d}}t^2\mu(t)S(\lfloor\frac{n}{dt}\rfloor)S(\lfloor\frac{m}{dt}\rfloor) \end{aligned} Ans==d=1min(n,m)dμ(d)S(dn)S(dm)tgcd(i,j),idn,jdmμ(t)d=1min(n,m)dμ(d)t=1dmin(n,m)t2μ(t)S(dtn)S(dtm)

这个 d t dt dt很麻烦,考虑直接枚举: A n s = ∑ T = 1 min ⁡ ( n , m ) S ( ⌊ n T ⌋ ) S ( ⌊ m T ⌋ )   T ∑ d ∣ T d μ ( d ) ∣ μ ( T d ) ∣ \begin{aligned} Ans=&\sum_{T=1}^{\min(n,m)}S(\lfloor\frac{n}T\rfloor)S(\lfloor\frac{m}T\rfloor)\,T\sum_{d\mid T}d\mu(d)|\mu(\frac{T}d)| \end{aligned} Ans=T=1min(n,m)S(Tn)S(Tm)TdTdμ(d)μ(dT)

前面那一坨已经可以考虑整除分块了,但是我们要找到一个高效的方法维护这个东西的前缀和: g ( T ) = T ∑ d ∣ T d μ ( d ) ∣ μ ( T d ) ∣ g(T)=T\sum_{d\mid T}d\mu(d)|\mu(\frac{T}d)| g(T)=TdTdμ(d)μ(dT)

其实就是这个东西 g = I d ⋅ ( ( I d ⋅ μ ) ∗ ∣ μ ∣ ) g=Id\cdot ((Id\cdot \mu)*|\mu|) g=Id((Idμ)μ)

我们知道积性函数的乘积和 D i r i c h l e t Dirichlet Dirichlet卷积结果仍然是积性函数,换句话说, g g g是积性函数,可以在线性筛的时候一起处理。

那么首先显然有:
g ( 1 ) = 1 g(1)=1 g(1)=1

∀ p ∈ P , g ( p ) = p ( 1 − p ) \forall p\in \mathbb P,g(p)=p(1-p) pP,g(p)=p(1p),这个可以通过直接展开得到

∀ p ∈ P , n ∈ N ∗ , g c d ( n , p ) = 1 , g ( p n ) = g ( p ) g ( n ) \forall p\in \mathbb P,n\in \mathbb N_*,gcd(n,p)=1,g(pn)=g(p)g(n) pP,nN,gcd(n,p)=1,g(pn)=g(p)g(n),这个由积性函数性质得到。

那么现在需要考虑的就是 p ∈ P , n ∈ N ∗ , g c d ( n , p ) = p p\in \mathbb P,n\in \mathbb N_*,gcd(n,p)=p pP,nN,gcd(n,p)=p,怎么求 g ( n p ) g(np) g(np)

首先,将 n n n分解: n = n ′ × p s n=n'\times p^s n=n×ps

如果 s ≥ 2 s\geq 2 s2,那么 n p np np中至少含有三个 p p p这个因子,那么这一项 μ ( d ) ∣ μ ( T d ) ∣ \mu(d)|\mu(\frac{T}d)| μ(d)μ(dT)就恒为 0 0 0(根据抽屉原理),此时 g ( n p ) = 0 g(np)=0 g(np)=0

不然, s = 1 s=1 s=1,我们可以得到: g ( n p ) = g ( n p ) g ( p 2 ) g(np)=g(\frac{n}p)g(p^2) g(np)=g(pn)g(p2)

考虑怎么求 g ( p 2 ) g(p^2) g(p2)

其实我们可以暴力展开:
g ( p 2 ) = p 2 ⋅ ( 1 ⋅ μ ( 1 ) ⋅ ∣ μ ( p 2 ) ∣ + p ⋅ μ ( p ) ∣ μ ( p ) ∣ + p 2 ⋅ μ ( p 2 ) ∣ μ ( 1 ) ∣ ) = − p 3 g(p^2)=p^2\cdot\big(1\cdot\mu(1)\cdot|\mu(p^2)|+p\cdot\mu(p)|\mu(p)|+p^2\cdot\mu(p^2)|\mu(1)|\big)=-p^3 g(p2)=p2(1μ(1)μ(p2)+pμ(p)μ(p)+p2μ(p2)μ(1))=p3

这道题就做完了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc putchar
#define cs const

namespace IO{
	namespace IOONLY{
		cs int Rlen=1<<18|1;
		char buf[Rlen],*p1,*p2;
	}
	inline char get_char(){
		using namespace IOONLY;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	
	inline int getint(){
		re int num;
		re char c;
		while(!isdigit(c=gc()));num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return num;
	}
}
using namespace IO;

cs int P=4000006;
int prime[P],pcnt;
int g[P];
bool mark[P];
inline void linear_sieves(int len=P-6){
	g[1]=1;
	for(int re i=2;i<=len;++i){
		if(!mark[i])prime[++pcnt]=i,g[i]=i*(1-i);
		for(int re j=1;i*prime[j]<=len;++j){
			mark[i*prime[j]]=true;
			if(i%prime[j]==0){
				if(i/prime[j]%prime[j])g[i*prime[j]]=-prime[j]*prime[j]*prime[j]*g[i/prime[j]];
				else g[i*prime[j]]=0;
				break;
			}
			g[i*prime[j]]=g[i]*g[prime[j]];
		}
	}
	for(int re i=2;i<=len;++i)g[i]+=g[i-1];
}

inline int S(cs int n){return n*(n+1ll)/2;}

inline int solve(int n,int m){
	if(n>m)swap(n,m);
	unsigned int ans=0;
	for(int re i=1,j;i<=n;i=j+1){
		j=min(n/(n/i),m/(m/i));
		ans+=(g[j]-g[i-1])*S(n/i)*S(m/i);
	}
	return ans&((1<<30)-1);
}

signed main(){
	linear_sieves();
	for(int re T=getint();T--;cout<<solve(getint(),getint())<<'\n');
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值