当前位置: 首页 > news >正文

【题解】洛谷P3768 简单的数学题[杜教筛]+两种欧反公式解析

(前排提示:这道题有两种方法)

这道题老抽了,很多人(包括我)想也不想的就直接莫比乌斯反演

\sum_{i=1}^{n}\sum_{j=1}^{n}i*j*gcd(i,j)

=\sum_{i=1}^{n}i\sum_{j=1}^{n}j\sum_{d=1}^{n}d*[gcd(i,j)=d]

=\sum_{d=1}^{n}d \sum_{i=1}^{\frac{n}{d}}id\sum_{j=1}^{\frac{n}{d}}jd*[gcd(i,j)=1]

=\sum_{d=1}^{n}d^3\sum_{i=1}^{\frac{n}{d}}i\sum_{j=1}^{\frac{n}{d}}j\sum_{a|gcd(i,j)}^{}\mu (a)

……巴拉巴拉的,这样,我就先不推了。

但是打住,冷静思考下,长这个样子的式子\sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j)

是不是还可以变成 \sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{a|i,a|j}^{}\varphi (a) 呢?

(因为 \sum_{d|n}^{}\varphi (n)=n,严格推导后面问问题的时候有)

那接着就是:

\sum_{i=1}^{n}\sum_{j=1}^{n}i*j\sum_{a|i,a|j}^{}\varphi (a)

=\sum_{a=1}^{n} \varphi (a)*a^2\sum_{i=1}^{\frac{n}{a}}\sum_{j=1}^{\frac{n}{a}}ij

=\sum_{a=1}^{n} \varphi (a)*a^2\sum_{i=1}^{\frac{n}{a}}\sum_{j=1}^{\frac{n}{a}}ij

=\sum_{a=1}^{n} \varphi (a)*a^2(\sum_{i=1}^{\frac{n}{a}}i)^2

=\sum_{a=1}^{n} \varphi (a)*a^2\sum_{i=1}^{\frac{n}{a}}i^3

但是 \sum_{a=1}^{n} \varphi (a)*a^2 前面的这个,因为 n 太大,没法直接前缀和

还得拿出来多造一个函数,搞一遍狄利克雷

我把推导写这里,本质上就是 \varphi *1*id*id=id*id*id

s(n)=\sum_{i=1}^{n}i*i*\varphi (i)

f=\varphi*id*id,g=1,(f*g)=id*id*id

g(1)s(n)=\sum_{i=1}^{n}(f*g)(i)-\sum_{i=2}^{n}g(i)id(i)id(i)s(\frac{n}{i})

1*s(n)=\sum_{i=1}^{n}id(i)*id(i)*id(i)-\sum_{d=2}^{n}(s(\frac{n}{d})*1*i*i)

s(n)=\sum_{i=1}^{n}i^3-\sum_{d=2}^{n}i^2*s(\frac{n}{d})

s(n)=(\frac{n(n+1)}{2})^2-\sum_{d=2}^{n}i^2*s(\frac{n}{d})

这个 {d=2}^{n}i^2 略有麻烦,需要两个平方和数列求和相减(又得造个函数)。

最后再分块加速就好了。

说回 \sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j)\Rightarrow \sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{a|i,a|j}^{}\varphi (a)

就像这道题一样,有时候,转换为欧拉函数会让我们省去很多步骤。

那到底什么时候可以转化为欧拉函数,什么时候会更方便

还有上面链接那道题和这道题的转化后的形式为什么不一样,选哪一种更好

先别急,我们先来解决第一个问题,也就是什么时候可以转化

回想下,我们有 \mu *id =\varphi。也就是 \sum_{d|n}^{}\mu (d)\frac{n}{d}=\varphi (n)

而这个东西 \sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j)莫反后刚好就是:

=\sum_{d=1}^{n}d\sum_{i=1}^{\frac{n}{d}}i\sum_{j=1}^{\frac{n}{d}}j\sum_{d=1}^{n}\sum_{a|gcd(i,j)}^{}\mu (a)

=\sum_{d=1}^{n}d\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}\sum_{a|gcd(i,j)}^{}\mu (a)

=\sum_{d=1}^{n}d\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}\sum_{a=1}^{\frac{n}{d}}\mu (a)[a|i][a|j]

=\sum_{d=1}^{n}d\sum_{a=1}^{\frac{n}{d}}\mu (a)\left \lfloor \frac{n}{ad} \right \rfloor^2

设 T=ad,则有:

=\sum_{d=1}^{n}d\sum_{\frac{T}{d}=1}^{\frac{n}{d}}\mu (\frac{T}{d})\left \lfloor \frac{n}{T} \right \rfloor^2

=\sum_{d=1}^{n}d\sum_{T=1}^{n}\mu (\frac{T}{d})\left \lfloor \frac{n}{T} \right \rfloor^2

=\sum_{T=1}^{n}\left \lfloor \frac{n}{T} \right \rfloor^2\sum_{d|T}^{}d*\mu (\frac{T}{d})

这个\sum_{d|T}^{}d*\mu (\frac{T}{d}),其实就是欧拉函数

=\sum_{T=1}^{n}\varphi (T)\left \lfloor \frac{n}{T} \right \rfloor^2

也就是只要出现 \sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j),就可以变成 \sum_{T=1}^{n}\varphi (T)\left \lfloor \frac{n}{T} \right \rfloor^2

(如果你认真做过莫反的题,会觉得上面的推导过程就像快乐老家一样)

那什么时候转化会更方便呢?其实大多数时候都会更好算,因为直接少了一个 for 循环。

(就是叫各位做数论题时看到 gcd 求和,就玩了命的推欧拉函数)

当然有且只有在 \sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j) 的时候可以用欧拉,其它像求 gcd 对数啊什么的还是老老实实莫反吧。

那为什么那道题和现在这道题的欧拉函数转化不一样呢?

很简单,我们比较 \sum_{T=1}^{n}\varphi (T)\left \lfloor \frac{n}{T} \right \rfloor^2 和 \sum_{d=1}^{n}\sum_{i=1}^{\frac{n}{d}}(2*\varphi (i)-1)

发现时间复杂度都是 O(\sqrt{n}),而后者还要加个 O(N) 的预处理

但大家发现了吗?T 和 d 是不同的!!也就是第一个公式改变了求和的变量,而第二个没有。

这个很重要!!!如果你需要求 \sum_{i=1}^{n}\sum_{j=1}^{n}f(gcd(i,j)) 的话,那你只能选第二种。

因为第一种把整个和式都大换洗了一遍,

化成 \sum_{T=1}^{n}\varphi (T)\left \lfloor \frac{n}{T} \right \rfloor^2 的话,你根本不知道 f 函数里面应该放什么。

而 \sum_{d=1}^{n}\sum_{i=1}^{\frac{n}{d}}(2*\varphi (i)-1) 还保留了最外面那个循环,

直接 \sum_{d=1}^{n}f(d)\sum_{i=1}^{\frac{n}{d}}(2*\varphi (i)-1) 就好。

我们这道题之所以选用 \sum_{T=1}^{n}\varphi (T)\left \lfloor \frac{n}{T} \right \rfloor^2,不仅是因为没有 f 函数,

还是因为 a^2\sum_{i=1}^{\frac{n}{a}}i^3 这坨很不好初始化,

加上 \sum_{d=1}^{n}\sum_{i=1}^{\frac{n}{d}}(2*\varphi (i)-1) 带到杜教筛里面就更灾难了。

讲了这么多,再复习这道题一遍公式:

\sum_{a=1}^{n} \varphi (a)*a^2\sum_{i=1}^{\frac{n}{a}}i^3

\sum_{i=1}^{n}i*i*\varphi (i)=(\frac{n(n+1)}{2})^2-\sum_{d=2}^{n}i^2*s(\frac{n}{d})
这题还有很多细节错误特别阴,大家如果遇到问题,可以去洛谷该题讨论区看看别人的经验。

直接看代码吧:

#include<bits/stdc++.h>
using namespace std;
const int N=5e6+10; 
typedef long long LL;
template<typename T> void qread(T &x){x=0; int f=1; char c=getchar();for(; !isdigit(c); c=getchar()) if(c=='-') f=-1;for(; isdigit(c); c=getchar()) x=x*10+(c-'0');x*=f;
}
LL P, n;
int phi[N], pr, prime[N]; //phi不能开longlong会炸 
LL sp[N], invtwo, invsix;
bool v[N];
void init(){pr=0; memset(v, 0, sizeof(v));phi[1]=1;for(int i=2; i<=N-10; i++){if(!v[i]){pr++; prime[pr]=i;phi[i]=i-1;}for(int j=1; (j<=pr) && (i*prime[j]<=N-10); j++){int p=prime[j];v[i*p]=1;if(i%p==0){phi[i*p]=phi[i]*p;break;}else{phi[i*p]=phi[i]*phi[p];}} }sp[0]=0;for(int i=1; i<=N-10; i++){sp[i]=(sp[i-1]+1LL*phi[i] *i%P*i)%P;}
}
LL q_pow(LL a, LL b){LL res=1;while(b){if(b&1) res=res*a%P;a=a*a%P; b/=2;}return res;
}
LL powsum(LL x){ //平方和数列求和 x%=P;return x*(x+1)%P*(2*x+1)%P*invsix%P;
}
LL getsum(LL x){ //自然数数列求和平方(就是i^3立方和数列的求和) x%=P;LL t=x*(x+1)%P*invtwo%P;return t*t%P;
}
map<LL, LL> hsp;
LL calc(LL x){ //欧拉函数*i*i求和 if(x<=N-10) return sp[x];if(hsp[x]) return hsp[x];LL res=getsum(x)%P;for(LL i=2, j; i<=x; i=j+1){j=x/(x/i);LL t=((powsum(j)-powsum(i-1))%P+P)%P;res=((res-t*calc(x/i)%P)+P)%P;}return hsp[x]=res;
}
LL solve(LL x){LL res=0;for(LL i=1, j; i<=x; i=j+1){j=x/(x/i);LL t=getsum(x/i)%P;res=(res+((calc(j)-calc(i-1))%P+P)%P*t%P)%P;}return res;
}
int main(){qread(P); qread(n);invtwo=q_pow(2, P-2);invsix=q_pow(6, P-2);init();printf("%lld\n", solve(n));return 0;
}
http://www.dtcms.com/a/318907.html

相关文章:

  • UDP网络编程chat
  • CompletableFuture的基础用法介绍
  • 技术优势铸就行业标杆:物联网边缘计算网关凭何引领智能变革?
  • 施耐德 Easy Altivar ATV310 变频器:高效电机控制的理想选择(含快速调试步骤及常见故障代码)
  • Flutter 局部刷新方案对比:ValueListenableBuilder vs. GetBuilder vs. Obx
  • 齐护机器人小智AI_MCP图形化编程控制Arduino_ESP32
  • 亚远景-ISO 42001:汽车AI安全的行业标准新趋势
  • 网站 博客遭遇DDoS,CC攻击应该怎样应对?
  • crew AI笔记[2] - 如何选型
  • MCU-TC397的UCB初识
  • 初识 MQ:从同步到异步,聊聊消息队列那些事
  • OpenCv对图片视频的简单操作
  • 深度学习(2):自动微分
  • 学深度学习,有什么好的建议或推荐的书籍?
  • MobileNetV3: 高效移动端深度学习的前沿实现
  • 从“炼金术”到“工程学”:深度学习十年范式变迁与未来十年路线图
  • 深度学习之opencv篇
  • HashMap寻址算法
  • QT项目 -仿QQ音乐的音乐播放器(第五节)
  • 《算法导论》第 10 章 - 基本数据结构
  • 深入剖析Java线程:从基础到实战(上)
  • ubuntu cloud init 20.04LTS升级到22.04LTS
  • vue3接收SSE流数据进行实时渲染日志
  • Web开发模式 前端渲染 后端渲染 身份认证
  • 第三章:【springboot】框架介绍MyBatis
  • Spring AOP动态代理核心原理深度解析 - 图解+实战揭秘Java代理设计模式
  • 前端百分比展示导致后端 BigDecimal 转换异常的排查与解决
  • 多账号管理方案:解析一款免Root的App分身工具
  • 【RabbitMQ面试精讲 Day 13】HAProxy与负载均衡配置
  • HTTP 协议升级(HTTP Upgrade)机制