Luogu 4213 【模板】杜教筛(Sum)
当作杜教筛的笔记吧。
杜教筛
要求一个积性函数$f(i)$的前缀和,现在这个东西并不是很好算,那么我们考虑让它卷上另外一个积性函数$g(i)$,使$(f * g)$的前缀和变得方便计算,然后再反推出这个$f$函数的前缀和。
$$\sum_{i = 1}^{n}(f * g)(i) = \sum_{i = 1}^{n}\sum_{d | i}g(d)f(\frac{i}{d}) = \sum_{d = 1}^{n}g(d)\sum_{i = 1}^{\left \lfloor \frac{n}{d} \right \rfloor}f(i) = \sum_{d = 1}^{n}g(d)S(\frac{n}{d}{})$$
把$g(1)S(n)$移过来
$$g(1)S(n) = \sum_{i = 1}^{n}(f * g)(i) - \sum_{i = 2}^{n}g(i)S(\left \lfloor \frac{n}{i} \right \rfloor)$$
这个式子就是杜教筛的精髓了。
我们可以先筛出$[1, \sqrt{n}]$区间内的该积性函数的前缀和,然后再分块递归求解$(\sqrt{n}, n]$中的该函数的前缀和,可以做到$O(n^{\frac{2}{3}})$的优秀的复杂度(并不会这个复杂度的证明)。
应该用一个哈希表存一下已经计算过的各个$S(n)$的值($unordered\_map$)。
接下来的问题就是考虑如何搭配出这个积性函数$g$了。
模板题
考虑如何计算$\mu$和$\varphi$。
我们知道$\mu * I = \epsilon$,那么有
$$S(n) = \sum_{i = 1}^{n}\epsilon(i) - \sum_{i = 2}^{n}S(\left \lfloor \frac{n}{i} \right \rfloor)$$
滑稽吧,$\epsilon$的前缀和还不是$1$。
我们又知道$\varphi * I = id$,那么又有
$$S(n) = \sum_{i = 1}^{n}id(i) - \sum_{i = 2}^{n}S(\left \lfloor \frac{n}{i} \right \rfloor)$$
而$\sum_{i = 1}^{n}id(i) = \sum_{i = 1}^{n}i = \frac{i(i + 1)}{2}$。
解决了!
Code:
#include <cstdio>
#include <cstring>
#include <unordered_map>
using namespace std;
typedef long long ll; const int N = 5e6 + ;
const int Maxn = 5e6; int testCase, pCnt = , pri[N], mu[N], phi[N];
ll sumMu[N], sumPhi[N];
bool np[N];
unordered_map <int, ll> sMu, sPhi; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for (; ch > ''|| ch < ''; ch = getchar())
if (ch == '-') op = -;
for (; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline void sieve() {
mu[] = , phi[] = ;
for (int i = ; i <= Maxn; i++) {
if (!np[i]) pri[++pCnt] = i, phi[i] = i - , mu[i] = -;
for (int j = ; j <= pCnt && i * pri[j] <= Maxn; j++) {
np[i * pri[j]] = ;
if (i % pri[j] == ) {
phi[i * pri[j]] = phi[i] * pri[j];
mu[i * pri[j]] = ;
break;
}
phi[i * pri[j]] = phi[i] * phi[pri[j]];
mu[i * pri[j]] = -mu[i];
}
} for (int i = ; i <= Maxn; i++) {
sumMu[i] = sumMu[i - ] + mu[i];
sumPhi[i] = sumPhi[i - ] + phi[i];
}
} ll getPhi(int n) {
if (n <= Maxn) return sumPhi[n];
if (sPhi[n]) return sPhi[n];
ll res = 1LL * n * (n + ) / ;
for (int l = , r; l <= n; l = r + ) {
r = (n / (n / l));
res -= 1LL * (r - l + ) * getPhi(n / l);
}
return sPhi[n] = res;
} ll getMu(int n) {
if (n <= Maxn) return sumMu[n];
if (sMu[n]) return sMu[n];
ll res = 1LL;
for (int l = , r; l <= n; l = r + ) {
r = (n / (n / l));
res -= 1LL * (r - l + ) * getMu(n / l);
}
return sMu[n] = res;
} int main() {
sieve();
read(testCase);
for (int n; testCase--; ) {
read(n);
printf("%lld %lld\n", getPhi(n), getMu(n));
}
return ;
}
感觉时限特别急,能别开$long \ long$就别开。
Luogu 4213 【模板】杜教筛(Sum)的更多相关文章
- p4213 【模板】杜教筛(Sum)
传送门 分析 我们知道 $\varphi * 1 = id$ $\mu * 1 = e$ 杜教筛即可 代码 #include<iostream> #include<cstdio> ...
- [模板] 杜教筛 && bzoj3944-Sum
杜教筛 浅谈一类积性函数的前缀和 - skywalkert's space - CSDN博客 杜教筛可以在\(O(n^{\frac 23})\)的时间复杂度内利用卷积求出一些积性函数的前缀和. 算法 ...
- luoguP4213 [模板]杜教筛
https://www.luogu.org/problemnew/show/P4213 同 bzoj3944 考虑用杜教筛求出莫比乌斯函数前缀和,第二问随便过,第一问用莫比乌斯反演来做,中间的整除分块 ...
- LG4213 【模板】杜教筛(Sum)和 BZOJ4916 神犇和蒟蒻
P4213 [模板]杜教筛(Sum) 题目描述 给定一个正整数$N(N\le2^{31}-1)$ 求 $$ans_1=\sum_{i=1}^n\varphi(i)$$ $$ans_2=\sum_{i= ...
- 51NOD 1222 最小公倍数计数 [莫比乌斯反演 杜教筛]
1222 最小公倍数计数 题意:求有多少数对\((a,b):a<b\)满足\(lcm(a,b) \in [1, n]\) \(n \le 10^{11}\) 卡内存! 枚举\(gcd, \fra ...
- BZOJ3944: Sum(杜教筛模板)
BZOJ3944: Sum(杜教筛模板) 题面描述 传送门 题目分析 求\(\sum_{i=1}^{n}\mu(i)\)和\(\sum_{i=1}^{n}\varphi(i)\) 数据范围线性不可做. ...
- luoguP4213 【模板】杜教筛(Sum)杜教筛
链接 luogu 思路 为了做hdu来学杜教筛. 杜教筛模板题. 卡常数,我加了register居然跑到不到800ms. 太深了. 代码 // luogu-judger-enable-o2 #incl ...
- [bzoj3944] sum [杜教筛模板]
题面: 传送门 就是让你求$ \varphi\left(i\right) $以及$ \mu\left(i\right) $的前缀和 思路: 就是杜教筛的模板 我们把套路公式拿出来: $ g\left( ...
- [洛谷P4213]【模板】杜教筛(Sum)
题目大意:给你$n$,求:$$\sum\limits_{i=1}^n\varphi(i),\sum\limits_{i=1}^n\mu(i)$$最多$10$组数据,$n\leqslant2^{31}- ...
随机推荐
- Navicat for MySQL导入.sql文件
首先,打开Navicat for MySQL,打开需要使用的连接,新建一个数据库名等按自己的需求填写. 打开创建的数据库,在空白处右键,选择运行SQL文件,然后找到.SQL文件所在地址即可. MySQ ...
- web 面试题、简单题、复习题
1. 概述MVC体系结构,各个部分都有那些技术来实现? M即model(模型,bean(domain)层)由javabean或EJB实现:V即view(视图,显示层)由jsp实现:C即controll ...
- Delphi AES加密(转)
(**************************************************************) (* Advanced Encryption Standard (AE ...
- notifyDataSetChanged() 动态更新ListView
有时候我们需要修改已经生成的列表,添加或者修改数据,notifyDataSetChanged()可以在修改适配器绑定的数组后,不用重新刷新Activity,通知Activity更新ListView.今 ...
- linux基础(3)
一 正文处理命令及tar命令 使用cat命令进行文件的纵向合并 两种文件的纵向合并方法 : tar命令的功能 : 掌握tar命令的功能:将多个文件(也可能包括目录,因为目录本身也是文件)放在一起存 ...
- thinkphp中的验证码的实现
1.php端生成验证码函数 public function verify(){ // 验证码 import("@.Util.Image"); Image::buildImageVe ...
- C语言中的未初始化变量的值
C语言中未初始化的变量的值是0么 全局变量 .静态变量初始值为0局部变量,自动变量初始值随机分配 C语言中,定义局部变量时如果未初始化,则值是随机的,为什么? 定义局部变量,其实就是在栈中通过移动栈指 ...
- ThreadStart中带参数
Thread Hand1 = new Thread(() => { MethodName(参数1, 参数2); }); Hand1 ...
- plsql中调试函数 转
1.首先在函数名上右键Test 2.进入调试界面后,界面下方会出现变量列表,在下图中value的栏中填入输入参数后,点击下图左上方带放大镜的绿色三角 3.此时进入调试模式,点击下图中的第一个蓝色方框, ...
- CDM中,创建一个或多个组合属性的唯一约束
除主键外,有时还需要创建一个或多个组合字段的唯一约束,方法如下: 双击打开实体,在idntifier标签页中可看到默认主键的唯一约束,在其下方添加一条记录,然后双击该记录,打开约束设置窗口 在该窗口的 ...