P3768 莫比乌斯反演 + 杜教筛

题目传送门

题意:

计算 \left ( \sum_{i=1}^{n}\sum_{j=1}^{n}ijgcd(i,j) \right ) \; mod \; p 。

p 是素数。

数据范围: 1 \leqslant n \leqslant 10^{10} , 5 \cdot 10^8 \leqslant p \leqslant 1.1 \cdot 10^9 。

题解:

这道题主要是考杜教筛。

这道题是 这篇博客 的强化版,就接着说了。

\begin{aligned} \sum_{i=1}^{n}\sum_{j=1}^{n}ijgcd(i,j) &= \sum_{d=1}^{n}d^3 \sum_{t=1}^{\left \lfloor \frac{n}{d} \right \rfloor} t^2\mu(t) (\sum_{i=1}^{\left \lfloor \frac{n}{td} \right \rfloor}i)^2 \end{aligned}

设 L(n) = (\sum_{i=1}^{n}i)^2 。

\begin{aligned} \sum_{i=1}^{n} \sum_{j=1}^{n} lcm(i,j) &= \sum_{d=1}^{n}d^3 \sum_{t=1}^{\left \lfloor \frac{n}{d} \right \rfloor} t^2\mu(t) L(\left \lfloor \frac{n}{td} \right \rfloor) \end{aligned}

可以整除分块套整除分块求解,现在的复杂度是 O(n),还需要优化,考虑常用套路换元。

令 T=td 。

\begin{aligned} \sum_{i=1}^{n}\sum_{j=1}^{n}ijgcd(i,j) &= \sum_{T=1}^{n} L(\left \lfloor \frac{n}{T} \right \rfloor) \sum_{d\mid T}d^3(\frac{T}{d})^2\mu(\frac{T}{d}) \\ &= \sum_{T=1}^{n}T^2L(\left \lfloor \frac{n}{T} \right \rfloor) \sum_{d\mid T}d\mu(\frac{T}{d}) \end{aligned}

然后有一个常用的连接欧拉函数和莫比乌斯函数的式子:\varphi(n) = \sum_{d\mid n}d\mu(\frac{n}{d}) 。

\begin{aligned} \sum_{i=1}^{n}\sum_{j=1}^{n}ijgcd(i,j) &= \sum_{T=1}^{n}T^2\varphi(T)L(\left \lfloor \frac{n}{T} \right \rfloor) \end{aligned}

设 f(n) = \sum_{i=1}^{n}i^2\varphi(n) 。

然后考虑整除分块去做,L 是可以 O(1) 计算的,主要就是计算 f 的前缀和。

因为前缀和必须低于线性计算,所以我们考虑杜教筛。

杜教筛常用套路:为了求 \sum_{i=1}^{n} f(i) ,我们构造积性函数 g ,然后令 h = f *g ,* 是狄利克雷卷积。

然后如果 \sum_{i=1}^{n} h(i) 很容易计算的话,那我们就可以求出来 \sum_{i=1}^{n} f(i) 了。

设 S(n)=\sum_{i=1}^{n} f(i) 。

杜教筛公式:g(1)S(n) = \sum_{i = 1}^{n}h(i) - \sum_{d=2}^{n}g(d)\cdot S(\left\lfloor \frac{n}{d} \right\rfloor)

然后我们怎么构造积性函数 g 呢?

先把 h 写出来吧。

\begin{aligned} h(n) &= f * g\\ &= \sum_{d\mid n} f(d) g(\frac{n}{d})\\ &= \sum_{d\mid n} d^2 \varphi(n) g(\frac{n}{d})\\ \end{aligned}

然后其实是一个套路,我们考虑消除 d^2 的方法去构造 g 。

令 g(n) = n^2 。

\begin{aligned} h(n) &= n^2 \sum_{d\mid n} \varphi(n)\\ \end{aligned}

然后又是一个常用式子:\sum_{d\mid n}\varphi(d) = n 。

然后 h(n) = n ^ 3 。

g(1)S(n) = \sum_{i = 1}^{n}h(i) - \sum_{d=2}^{n}g(d)\cdot S(\left\lfloor \frac{n}{d} \right\rfloor)

转化为

S(n) = \sum_{i = 1}^{n}h(i) - \sum_{d=2}^{n}d^2\cdot S(\left\lfloor \frac{n}{d} \right\rfloor)

然后我们就可以递归求解 S(n) 了。

有两个需要优化的地方:

(1)你需要线性筛 5e6 以内的 S(n) ,这样会少递归很多次。

(2)map 存储递归求解出的 S(n) ,这样也会少递归很多次。

感受:

第一次做杜教筛,感觉有点像高中学的化学方程式配平。

代码:

#include<bits/stdc++.h>
using namespace std ;
typedef long long ll ;
typedef pair<int , int> pli ;
const int maxn = 5e6 + 5 ;
ll mod ;
ll six , two ;
map<ll , ll> s ; 
int phi[maxn] ;
ll pre[maxn] ;
int num = 5e6 ;
void eular(int n)
{
   phi[1] = 1 ;
   for(int i = 2 ; i <= n ; i ++)  phi[i] = i ;
   for(int i = 2 ; i <= n ; i ++)
     if(phi[i] == i)
       for(int j = i ; j <= n ; j += i)
         phi[j] = phi[j] / i * (i - 1) ; 
   for(int i = 1 ; i <= n ; i ++)
     pre[i] = pre[i - 1] + ll(i) * i % mod * phi[i] % mod ,
     pre[i] %= mod ;
}
ll qpow(ll a , ll b)
{
   ll ans = 1 ; 
   a %= mod ;
   while(b)
   {
     if(b & 1)  ans = (ans * a) % mod ;
     b >>= 1 , a = (a * a) % mod ;
   }
   return ans % mod ;
}
ll inv(ll n)
{
	return qpow(n , mod - 2) % mod ;
}
ll sum(ll n)
{
	n %= mod ;
	ll c = n * (n + 1) % mod ;
	c *= two , c %= mod ;
	return c * c % mod ;
}
ll sum2(ll n)
{
	n %= mod ;
	ll c = n * (n + 1) % mod * (2 * n + 1) % mod ;
	c *= six , c %= mod ;
	return c ;
}
ll dls(ll n)
{
	if(n <= num)  return pre[n] ;
	if(s[n])  return s[n] ;
	//cout << n << '\n' ;
	ll ans = sum(n) ;
	for(ll l = 2 , r ; l <= n ; l = r + 1)
	{
		r = n / (n / l) ;
		ll c = (sum2(r) - sum2(l - 1) + mod) % mod ;
		ans -= c * dls(n / l) ;
		ans %= mod ;
	}
	ans = (ans + mod) % mod ;
	s[n] = ans ;
	return ans ;
}
void solve(ll n)
{
	ll ans = 0 ;
	for(ll l = 1 , r ; l <= n ; l = r + 1)
	{
		r = n / (n / l) ;
		ll c = (dls(r) - dls(l - 1) + mod) % mod ;
		ans += c * sum(n / l) ;
		ans %= mod ;
	}
	printf("%lld\n" , ans) ;
}
int main()
{
	ll n , m ;
	scanf("%lld%lld" , &mod , &n) ;
	eular(num) ;
	six = inv(6ll) ;
	two = inv(2ll) ;
	solve(n) ;
	return 0 ;
}

 

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值