[51Nod 1244] - 莫比乌斯函数之和 & [51Nod 1239] - 欧拉函数之和 (杜教筛板题)
[51Nod 1244] - 莫比乌斯函数之和
求∑i=1Nμ(i)\sum_{i=1}^Nμ(i)∑i=1Nμ(i)
开推
∑d∣nμ(d)=[n==1]\sum_{d|n}\mu(d)=[n==1]d∣n∑μ(d)=[n==1]
移项
μ(d)=[n==1]−∑d∣n,d<nμ(d)∴S(N)=∑i=1Nμ(i)=∑i=1N([i==1]−∑d∣i,d<iμ(d))=1−∑i=1N∑d∣i,d<iμ(d)\mu(d)=[n==1]-\sum_{d|n,d<n}\mu(d)\newline
\therefore S(N)=\sum_{i=1}^Nμ(i)=\sum_{i=1}^N([i==1]-\sum_{d|i,d<i}\mu(d))\newline
=1-\sum_{i=1}^N\sum_{d|i,d<i}\mu(d) \newlineμ(d)=[n==1]−d∣n,d<n∑μ(d)∴S(N)=i=1∑Nμ(i)=i=1∑N([i==1]−d∣i,d<i∑μ(d))=1−i=1∑Nd∣i,d<i∑μ(d)
此处是杜教筛的精髓,也是整除分块优化的精髓(或者说是转换方法),枚举i是d的多少倍
S(N)=1−∑⌊id⌋=2N∑d=1,1<⌊id⌋⌊N⌊id⌋⌋μ(d)S(N)=1-\sum_{{\lfloor{\frac id}\rfloor} =2}^N\sum_{d=1,1<{\lfloor{\frac id}\rfloor}}^{\lfloor \frac N{\lfloor{\frac id}\rfloor} \rfloor}\mu(d)S(N)=1−⌊di⌋=2∑Nd=1,1<⌊di⌋∑⌊⌊di⌋N⌋μ(d)
令k=⌊id⌋k={\lfloor{\frac id}\rfloor}k=⌊di⌋,则有
S(N)=1−∑k=2N∑d=1⌊Nk⌋μ(d)=1−∑k=2NS(⌊Nk⌋)S(N)=1-\sum_{k=2}^N\sum_{d=1}^{\lfloor \frac Nk\rfloor}\mu(d)
=1-\sum_{k=2}^NS({\lfloor \frac Nk\rfloor})S(N)=1−k=2∑Nd=1∑⌊kN⌋μ(d)=1−k=2∑NS(⌊kN⌋)
那么就可以用线性筛出前面一部分,再整除分块优化递归处理
杜教筛无预处理的时间复杂度是Θ(n34)\Theta(n^{\frac 34})Θ(n43)
预处理一定范围内的答案后就能降到Θ(n23)\Theta(n^{\frac 23})Θ(n32)
然而我们此处并不需要多小的时间复杂度…随便处理一个10710^7107就能过了
AC code
#include <cstdio>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
const int MAXP = 1e7+1;
int Prime[MAXP/10], Cnt, mu[MAXP], sum[MAXP];
bool IsnotPrime[MAXP];
map<LL,int>S;
void init(int N)
{
mu[1] = 1;
for(int i = 2; i <= N; ++i)
{
if(!IsnotPrime[i]) Prime[++Cnt] = i, mu[i] = -1;
for(int j = 1; j <= Cnt && i * Prime[j] <= N; ++j)
{
IsnotPrime[i * Prime[j]] = 1;
if(i % Prime[j] == 0) { mu[i * Prime[j]] = 0; break; }
mu[i * Prime[j]] = -mu[i];
}
}
for(int i = 1; i <= N; i++) sum[i] = sum[i-1] + mu[i];
}
inline int solve(LL N)
{
if(N < MAXP) return sum[N];
if(S.count(N)) return S[N];//记忆化,其实此处可以Hash或者用
int ret = 1;
for(LL i = 2, j; i <= N; i=j+1)
{
j = N/(N/i);
ret -= (j-i+1) * solve(N/i);
}
return S[N] = ret;
}
int main ()
{
LL n, m; init(MAXP-1);
scanf("%lld%lld", &n, &m);
printf("%d\n", solve(m)-solve(n-1));
}
[51Nod 1239] - 欧拉函数之和
求 ∑i=1Nφ(i)\sum_{i=1}^Nφ(i)∑i=1Nφ(i)
开推,有
∑d∣nφ(d)=n
\sum_{d|n}φ(d)=n
d∣n∑φ(d)=n
移项
φ(n)=n−∑d∣n,d<nφ(d)∴S(N)=∑i=1N(i−∑d∣i,d<iφ(d))=N∗(N+1)2−∑i=1N∑d∣i,d<iφ(d)=N∗(N+1)2−∑⌊id⌋=2N∑d=1⌊N⌊id⌋⌋φ(d)
φ(n)=n-\sum_{d|n,d<n}φ(d)\newline
\therefore S(N)=\sum_{i=1}^N(i-\sum_{d|i,d<i}φ(d))\newline
=\frac{N*(N+1)}2-\sum_{i=1}^N\sum_{d|i,d<i}φ(d)\newline
=\frac{N*(N+1)}2-\sum_{{\lfloor\frac id\rfloor}=2}^N\sum_{d=1}^{{\lfloor\frac N{{\lfloor\frac id\rfloor}}\rfloor}}φ(d)\newlineφ(n)=n−d∣n,d<n∑φ(d)∴S(N)=i=1∑N(i−d∣i,d<i∑φ(d))=2N∗(N+1)−i=1∑Nd∣i,d<i∑φ(d)=2N∗(N+1)−⌊di⌋=2∑Nd=1∑⌊⌊di⌋N⌋φ(d)
令k=⌊id⌋k={\lfloor{\frac id}\rfloor}k=⌊di⌋,则有
S(N)=N∗(N+1)2−∑k=2N∑d=1⌊Nk⌋φ(d)=N∗(N+1)2−∑k=2NS(⌊Nk⌋)
S(N)=\frac{N*(N+1)}2-\sum_{k=2}^N\sum_{d=1}^{{\lfloor\frac Nk\rfloor}}φ(d)\newline
=\frac{N*(N+1)}2-\sum_{k=2}^NS({\lfloor\frac Nk\rfloor})\newline
S(N)=2N∗(N+1)−k=2∑Nd=1∑⌊kN⌋φ(d)=2N∗(N+1)−k=2∑NS(⌊kN⌋)
然后…就没有了.像上一道题一样处理就完了
AC Code
#include <cstdio>
#include <map>
#include <cstring>
#include <algorithm>
using namespace std;
#define LL long long
const int MAXP = 5e6 + 1;
const int mod = 1e9 + 7;
const int inv2 = 500000004;
int Prime[MAXP/10], Cnt, phi[MAXP];
LL sum_phi[MAXP];
bool IsnotPrime[MAXP];
void init(int N)
{
phi[1] = 1;
for(LL i = 2; i <= N; ++i)
{
if(!IsnotPrime[i]) Prime[++Cnt] = i, phi[i] = i-1;
for(LL j = 1; j <= Cnt && i * Prime[j] <= N; ++j)
{
IsnotPrime[i * Prime[j]] = 1;
if(i % Prime[j] == 0)
{
phi[i * Prime[j]] = phi[i] * Prime[j];
break;
}
phi[i * Prime[j]] = phi[i] * (Prime[j]-1);
}
}
for(int i = 1; i <= N; i++)
sum_phi[i] = ((sum_phi[i-1] + phi[i]) % mod + mod) % mod;
}
map<LL, LL> S_phi;
inline LL solve_phi(LL N)
{
if(N < MAXP) return sum_phi[N];
if(S_phi.count(N)) return S_phi[N];
LL ret = (N%mod + 1) * (N%mod) % mod * inv2 % mod;
for(LL i = 2, j; i <= N; i=j+1)
{
j = N/(N/i);
ret = (ret - (j-i+1) % mod * solve_phi(N/i) % mod) % mod;
}
return S_phi[N] = ((ret + mod) % mod);
}
int main ()
{
init(MAXP-1); LL n;
scanf("%lld", &n);
printf("%lld\n", solve_phi(n));
}
[51Nod 1244] - 莫比乌斯函数之和 & [51Nod 1239] - 欧拉函数之和 (杜教筛板题)的更多相关文章
- 51 NOD 1239 欧拉函数之和(杜教筛)
1239 欧拉函数之和 基准时间限制:3 秒 空间限制:131072 KB 分值: 320 难度:7级算法题 收藏 关注 对正整数n,欧拉函数是小于或等于n的数中与n互质的数的数目.此函数以其首名研究 ...
- BZOJ_4802_欧拉函数_MR+pollard rho+欧拉函数
BZOJ_4802_欧拉函数_MR+pollard rho+欧拉函数 Description 已知N,求phi(N) Input 正整数N.N<=10^18 Output 输出phi(N) Sa ...
- 51nod 1239 欧拉函数之和(杜教筛)
[题目链接] https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1239 [题目大意] 计算欧拉函数的前缀和 [题解] 我们 ...
- 51nod 1237 最大公约数之和 V3【欧拉函数||莫比乌斯反演+杜教筛】
用mu写lcm那道卡常卡成狗(然而最后也没卡过去,于是写一下gcd冷静一下 首先推一下式子 \[ \sum_{i=1}^{n}\sum_{j=1}^{n}gcd(i,j) \] \[ \sum_{i= ...
- 51Nod 1239 欧拉函数前n项和 杜教筛
http://www.51nod.com/Challenge/Problem.html#!#problemId=1239 AC代码 #include <bits/stdc++.h> #de ...
- 【51nod】1239 欧拉函数之和 杜教筛
[题意]给定n,求Σφ(i),n<=10^10. [算法]杜教筛 [题解] 定义$s(n)=\sum_{i=1}^{n}\varphi(i)$ 杜教筛$\sum_{i=1}^{n}(\varph ...
- 【51nod】1239 欧拉函数之和
题解 写完上一道就开始写这个,大体上就是代码改了改而已= = 好吧,再推一下式子! \(\sum_{i = 1}^{n}i = \sum_{i = 1}^{n}\sum_{d | i}\phi(d) ...
- 51nod 1239 欧拉函数之和【欧拉函数+杜教筛】
和bzoj 3944比较像,但是时间卡的更死 设\( f(n)=\sum_{d|n}\phi(d) g(n)=\sum_{i=1}^{n}f(i) s(n)=\sum_{i=1}^{n}\phi(i) ...
- 51nod 1238 最小公倍数之和 V3 【欧拉函数+杜教筛】
首先题目中给出的代码打错了,少了个等于号,应该是 G=0; for(i=1;i<=N;i++) for(j=1;j<=N;j++) { G = (G + lcm(i,j)) % 10000 ...
随机推荐
- 剑指offer54:字符流中第一个不重复的字符
1 题目描述 请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g".当从该字符流中 ...
- Java正则表达式获取中括号之间的内容
参考: 求一个正则表达式提取中括号里的内容 [问题点数:80分]CSDN论坛 > Java > Web 开发 正则表达式 - 菜鸟教程 不包含中括号 正则表达式如下: \\[(.*?)] ...
- Vue.js 2.x 混入
Vue.js 2.x mixins 混入 混入(mixins)是一种分发vue组件中可复用功能的非常灵活的方式.混入对象可以包含任意组件选项.当组件使用混入对象时,所有混入对象的选项将被混入该组件本身 ...
- NetLink通信原理研究、Netlink底层源码分析、以及基于Netlink_Connector套接字监控系统进程行为技术研究
1. Netlink简介 0x1:基本概念 Netlink是一个灵活,高效的”内核-用户态“.”内核-内核“.”用户态-用户态“通信机制.通过将复杂的消息拷贝和消息通知机制封装在统一的socket a ...
- pip源设置为国内源
windows系统步骤如下: (1)打开文件资源管理器(文件夹地址栏中) (2)地址栏上面输入 %appdata% (3)在这里面新建一个文件夹 pip (4)在pip文件夹里面新建一个文件叫做 pi ...
- mybatis获取刚刚插入到数据库的数据的id(转载)
原文地址:https://blog.csdn.net/hehuihh/article/details/82800739 我用的是第一种写法,直接把代码copy到insert标签里(id要是自增id) ...
- 将netcore网站部署到docker容器中
一.背景 最近一直在看docker的教程,基础知识看的差不多了.理论总要运用于实践,所以下面我们就来把最简单的一个netcore网站托管到docker容器中. 环境:1.docker for wind ...
- 【转载】Sqlserver存储过程中使用Select和Set给变量赋值
Sqlserver存储过程是时常使用到的一个数据库对象,在存储过程中会使用到Declare来定义存储过程变量,定义的存储过程变量可以通过Set或者Select等关键字方法来进行赋值操作,使用Set对存 ...
- js展开循环
当要对一个大数组进行循环时,通常会通过局部变量缓存数组长度来提高性能,例: for(var i=0,len=arr.len;i<len;i++){} 光是缓存数组长度或使用倒序遍历来减少判断外, ...
- [ipsec][strongswan] strongswan源码分析--(四)plugin加载优先级原理
前言 如前所述, 我们知道,strongswan以插件功能来提供各种各样的功能.插件之间彼此相互提供功能,同时也有可能提供重复的功能. 这个时候,便需要一个优先级关系,来保证先后加载顺序. 方法 在配 ...