51Nod2026 Gcd and Lcm-题解

题目地址

题意简述

我们令 f ( n ) = ∑ d ∣ n μ ( d ) d f(n)=\sum_{d|n}\mu(d)d f(n)=dnμ(d)d,求下面式子在模 998244353 998244353 998244353后的值:

∑ i = 1 n ∑ j = 1 n f ( g c d ( i , j ) ) × f ( l c m ( i , j ) ) \sum_{i=1}^n\sum_{j=1}^nf(gcd(i,j))\times f(lcm(i,j)) i=1nj=1nf(gcd(i,j))×f(lcm(i,j))

其中 g c d gcd gcd为最大公约数, l c m lcm lcm为最小公倍数。


我们先来看一个例子:

求:
∑ i = 1 n ∑ j = 1 n g c d ( i , j ) × l c m ( i , j ) \sum_{i=1}^n\sum_{j=1}^ngcd(i,j)\times lcm(i,j) i=1nj=1ngcd(i,j)×lcm(i,j)

很容易知道,这个可以这样变换:

∑ i = 1 n ∑ j = 1 n g c d ( i , j ) i j g c d ( i , j ) = ∑ i = 1 n ∑ j = 1 n i j = ( ∑ i = 1 n i ) ( ∑ j = 1 n j )   = ( ∑ i = 1 n i ) 2 \sum_{i=1}^n\sum_{j=1}^ngcd(i,j)\frac{ij}{gcd(i,j)} \\ =\sum_{i=1}^n\sum_{j=1}^nij \\ =\left(\sum_{i=1}^ni\right)\left(\sum_{j=1}^nj\right) \\\ \\ =\left(\sum_{i=1}^ni\right)^2 i=1nj=1ngcd(i,j)gcd(i,j)ij=i=1nj=1nij=(i=1ni)(j=1nj) =(i=1ni)2

所以我们看,原来的式子是否也能这样变换。

首先我们可以知道 f = ( μ ⋅ i d ) ∗ 1 f=(\mu\cdot id)*\mathbf 1 f=(μid)1(其中 ∗ * 为狄利克雷卷积)。

由于积性函数的乘积以及狄利克雷卷积仍旧为积性函数,所以 f f f也为积性函数。

那么我们考虑,对于一对 i , j i,j i,j,我们根据唯一分解定理,假设:

i = ∏ p x a x   j = ∏ p y b y i=\prod p_x^{a_x} \\\ \\ j=\prod p_y^{b_y} i=pxax j=pyby

那么 f ( g c d ( i , j ) ) × f ( l c m ( i , j ) ) f(gcd(i,j))\times f(lcm(i,j)) f(gcd(i,j))×f(lcm(i,j))可以写成:

∏ f ( p w m i n ( a w , b w ) ) ∏ f ( p w m a x ( a w , b w ) ) \prod f(p_w^{min(a_w,b_w)}) \prod f(p_w^{max(a_w,b_w)}) f(pwmin(aw,bw))f(pwmax(aw,bw))
(其中是因为积性函数 f ( x y ) = f ( x ) f ( y ) f(xy)=f(x)f(y) f(xy)=f(x)f(y),在 x ⊥ y x\perp y xy时(互质),所以将 i , j i,j i,j拆开)

那么我们将属于 i i i的放在一起,属于 j j j的放在一起,可以得到:

∏ f ( p x a x ) ∏ f ( p y a y ) = f ( i ) f ( j ) \prod f(p_x^{a_x})\prod f(p_y^{a_y}) \\ =f(i)f(j) f(pxax)f(pyay)=f(i)f(j)

所以就可以按照前面的例子的做法,将其分开变换后可以得到,原式等于:

( ∑ i = 1 n f ( i ) ) 2 \left(\sum_{i=1}^n f(i)\right)^2 (i=1nf(i))2

那么现在我们考虑如何求 f f f的前缀和,由于 n ≤ 1 0 9 n\leq 10^9 n109,所以要用杜教筛。

我们看, f = ( μ ⋅ i d ) ∗ 1 f=(\mu\cdot id)*\mathbf 1 f=(μid)1,那么我们令 g = i d g=id g=id,则 f ∗ g f*g fg就等于:

f ∗ g = ( μ ⋅ i d ) ∗ 1 ∗ i d = ( μ ⋅ i d ) ∗ i d ∗ 1 = ( ∑ d ∣ n μ ( d ) d × n d ) ∗ 1 = ( n ∑ d ∣ n μ ( d ) ) ∗ 1 = ( i d ⋅ ϵ ) ∗ 1 = ϵ ∗ 1 = 1 \begin{aligned} f*g=&(\mu\cdot id)*\mathbf 1 * id \\ =&(\mu\cdot id)*id*\mathbf 1 \\ =&\left(\sum_{d|n}\mu(d)d\times \frac{n}{d}\right)*\mathbf 1 \\ =& \left(n\sum_{d|n}\mu(d)\right)*\mathbf 1 \\ =&(id\cdot \epsilon )*\mathbf 1 \\ =&\epsilon * \mathbf 1 \\ =& \mathbf 1 \end{aligned} fg=======(μid)1id(μid)id1dnμ(d)d×dn1ndnμ(d)1(idϵ)1ϵ11

那么我们将其带入杜教筛的公式,可以得到前缀和等于:

S ( n ) = ∑ i = 1 n 1 − ∑ i = 2 n i S ( ⌊ n i ⌋ ) S(n)=\sum_{i=1}^n 1-\sum_{i=2}^ni S(\lfloor\frac{n}{i}\rfloor) S(n)=i=1n1i=2niS(in)

我们预处理 n 2 3 n^{\frac{2}{3}} n32的前缀和,然后杜教筛就好啦。

关于 f f f的线性筛,方法如下:

因为当 μ ( p c ) \mu(p^c) μ(pc) c > 1 c>1 c>1 μ ( p c ) = 0 \mu(p^c)=0 μ(pc)=0,所以原式为:

f ( p c ) = ∑ i = 0 c μ ( p i ) p i = 1 − p f(p^c)=\sum_{i=0}^c\mu(p^i)p^i=1-p f(pc)=i=0cμ(pi)pi=1p
根据积性函数定义:
f ( p c ) = 1 − p f ( x × p c ) = f ( p c ) f ( x ) [ x ⊥ p c ] f(p^c)=1-p \\ f(x\times p^c)=f(p^c)f(x)[x\perp p^c] f(pc)=1pf(x×pc)=f(pc)f(x)[xpc]

所以这个题就可以在 O ( n 2 3 ) O(n^{\frac{2}{3}}) O(n32)时间内解决了。

#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int M=1e6+10;
const ll Mod=1e9+7;
ll prime[M],mu[M],cnt;
bool vis[M];
ll F[M],c[M],f[M],inv_2;
ll fpow(ll a,ll b){
	ll res=1;
	for(;b;b>>=1,a=(a*a)%Mod){
		if(b&1)res=(res*a)%Mod;
	}
	return res;
}
void init(){
	inv_2=fpow(2,Mod-2);
	F[1]=1;
	for(ll i=2;i<M;i++){
		if(!vis[i]){
			prime[++cnt]=i;
			F[i]=((1-i)%Mod+Mod)%Mod;
			c[i]=i;f[i]=i;
		}
		for(ll j=1,v;j<=cnt&&i*prime[j]<M;j++){
			v=i*prime[j];
			vis[v]=1;
			if(!(i%prime[j])){
				c[v]=c[i]*f[i];f[v]=f[i];
				F[v]=F[v/c[v]]*F[prime[j]]%Mod;
				break;
			}
			F[v]=F[i]*F[prime[j]]%Mod;
			c[v]=prime[j];f[v]=prime[j];
		}
	}
	for(ll i=2;i<M;i++){
		F[i]=(F[i-1]+F[i])%Mod;
	}
}
ll S(ll x){return ((x*(x+1))%Mod)*inv_2%Mod;}
ll Sarea(ll L,ll R){return ((S(R)-S(L-1))%Mod+Mod)%Mod;}
map <ll,ll> mp;
ll calc(ll x){
	if(x<M) return F[x];
	if(mp.count(x)) return mp[x];
	ll ans=x;
	for(ll i=2,j;i<=x;i=j+1){
		j=(x/(x/i));
		ans=(ans-(Sarea(i,j)*calc(x/i))%Mod)%Mod;
	}
	if(ans<0)ans+=Mod;
	return mp[x]=ans;
}
ll n;
ll Sqr(ll a){return a*a%Mod;}
int main(){
	scanf("%lld",&n);
	init();
	printf("%lld\n",Sqr(calc(n)));
	return 0;
}

End

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VictoryCzt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值