Note -「Maths」Euler 筛筛积性函数
Part. 1 Preface
这个东西是我在做 JZPTAB 的时候 LYC 给我讲的。
然后发现这是个通法,就写一写。
本文除了例题所有代码均未经过编译,仅作为参考。
Part. 2 Untitled(怎么取标题呀)(哦 正文)
Part. 2-1 Worse ver.
对于一个积性函数 \(f(n)\),如果我们已知 \(f(1),f(p),f(p^{k})\) (\(p\) 是一个素数)并且可以在 \(O(\log_{2}(n))\) 的时间内算出来的话,我们就可以在 \(O(n\log_{2}(n))\) 的时间内利用 Euler 筛筛出 \(f(1\cdots n)\) 的值。
举个例子,假设
\]
由于 \(\text{id}\) 卷 \(\varphi\) 卷不出个什么现成的函数,所以我们得考虑自己把它筛出来。
带个 \(p\) 进去可知
f(1)=1 \\
\displaystyle
f(p)=2\times p-1 \\
\displaystyle
f(p^{k})=(k+1)\times p^{k}-k\times p^{k-1}
\end{cases}
\]
以下内容请参考 Euler 筛代码来看:
void sieve ( const int x ) {
tag[1] = 1, f[1] = /* DO SOMETHING 1 */;
for ( int i = 2; i <= x; ++ i ) {
if ( ! tag[i] ) {
pSet[++ psc] = i;
f[i] = /* DO SOMETHING 2 */;
}
for ( int j = 1; j <= psc && pSet[j] * i <= x; ++ j ) {
tag[pSet[j] * i] = 1;
if ( ! ( i % pSet[j] ) ) {
f[pSet[j] * i] = /* DO SOMETHING 3 */;
break;
}
else f[pSet[j] * i] = /* DO SOMETHING */;
}
}
}
函数 \(\text{sieve}\) 就是 Euler 筛的过程。我在代码中留了四个空,分别来看我们需要做什么。
第一个空很显然,把 \(f(1)\) 赋给
f[1]即可。第二个空也很显,把 \(f(p)\) 付给
f[i]。我们重点来看第三个空。
首先因为此时的 \(i,\text{pSet}_{j}\) 不互质,所以不能直接照完全积性函数筛。
首先,我们需要把 \(i\times\text{pSet}_{j}\) 中 \(\text{pSet}_{j}\) 因子全部除掉,除完后的结果记为 \(\text{tmp}\),\(\text{pSet}_{j}\) 因子数量记为 \(\text{power}\),即 \(i\times\text{pSet}_{j}=\text{pSet}_{j}^{\text{power}}\times c\)。
就是类似下面代码做的事情
int tmp = i / pSet[j], power = 2;
while ( ! ( i % pSet[j] ) ) i /= pSet[j], ++ power;
然后对 \(\text{tmp}\) 进行分类讨论:
- \(\text{tmp}=1\):此时 \(i\times\text{pSet}_{j}\) 是 \(\text{pSet}_{j}\) 的 \(\text{power}\) 次方,把 \(f(p^{k})\) 赋给
f[pSet[j] * i]即可。
- \(\text{tmp}=1\):此时 \(i\times\text{pSet}_{j}\) 是 \(\text{pSet}_{j}\) 的 \(\text{power}\) 次方,把 \(f(p^{k})\) 赋给
- \(\text{tmp}>1\):此时 \(\text{tmp}\) 与 \(\frac{i\times\text{pSet}_{j}}{\text{tmp}}\) 互质,于是照积性函数
f[pSet[j] * i] = f[pSet[j] * i / tmp] * f[tmp]。
- \(\text{tmp}>1\):此时 \(\text{tmp}\) 与 \(\frac{i\times\text{pSet}_{j}}{\text{tmp}}\) 互质,于是照积性函数
于是第三个空做完了。
- 第四个空中 \(\text{pSet}_{j}\) 与 \(i\) 互质,于是照积性函数
f[pSet[j] * i] = f[pSet[j]] * f[i]。
于是我们得到了完整代码
void sieve ( const int x ) {
tag[1] = 1, f[1] = 1;
for ( int i = 2; i <= x; ++ i ) {
if ( ! tag[i] ) {
pSet[++ psc] = i;
f[i] = 2 * i - 1;
}
for ( int j = 1; j <= psc && pSet[j] * i <= x; ++ j ) {
tag[pSet[j] * i] = 1;
if ( ! ( i % pSet[j] ) ) {
int tmp = i / pSet[j], power = 2;
while ( ! ( i % pSet[j] ) ) i /= pSet[j], ++ power;
if ( tmp == 1 ) f[pSet[j] * i] = ( power + 1 ) * cqpow ( pSet[j], power ) - power * cqpow ( pSet[j], power - 1 );
else f[pSet[j] * i] = f[pSet[j] * i / tmp] * f[tmp];
break;
}
else f[pSet[j] * i] = f[pSet[j]] * f[i];
}
}
}
Part. 2-2 Better ver.
上述的方法的缺点显而易见:复杂度多出来个 \(\log_{2}\)。
更好的方法是记录最小质因子,具体见 ljs 博客 Link。
Part. 3 Example
LOCAL 64388 - GCD SUM
求
\[\sum_{i=1}^n\sum_{j=1}^m\textrm{gcd}(i,j)
\]共有 \(T\) 组询问
\(\text{task_id}\) 测试点数 \(n,m\leq\) \(T\leq\) 特殊性质 \(1\) 1\(10\) \(10^3\) 无 \(2\) 2\(10^3\) \(10\) 无 \(3\) 3\(10^3\) \(10^4\) 无 \(4\) 4\(10^6\) \(10\) \(n = m\) \(5\) 5\(10^6\) \(10^4\) \(n = m\) \(6\) 2\(10^6\) \(10^5\) \(n = m\) \(7\) 3\(10^7\) \(10^6\) \(n = m\) \(8\) 2\(10^6\) \(10\) 无 \(9\) 3\(10^6\) \(10^4\) 无
放个 task 7 以外的部分分的推导
\begin{aligned}
&=\sum_{d=1}^{\min\{n,m\}}d\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=d] \\
&=\sum_{d=1}^{\min\{n,m\}}d\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[\gcd(i,j)=1] \\
&=\sum_{d=1}^{\min\{n,m\}}d\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}\sum_{k|i,k|j}\mu(k) \\
&=\sum_{d=1}^{\min\{n,m\}}d\sum_{k|(\lfloor\frac{n}{d}\rfloor),k|(\lfloor\frac{m}{d}\rfloor)}\mu(k)(\lfloor\frac{n}{d\times k}\rfloor)(\lfloor\frac{m}{d\times k}\rfloor) \\
&=\sum_{d=1}^{\min\{n,m\}}d\sum_{k|(\lfloor\frac{n}{d}\rfloor),k|(\lfloor\frac{m}{d}\rfloor)}\mu(k)(\lfloor\frac{n}{d\times k}\rfloor)(\lfloor\frac{m}{d\times k}\rfloor) \\
&=\sum_{T=1}^{\min\{n,m\}}\sum_{d|T}d\times\mu(\lfloor\frac{T}{d}\rfloor)\times(\lfloor\frac{n}{T}\rfloor)\times(\lfloor\frac{m}{T}\rfloor) \\
&=\sum_{T=1}^{\min\{n,m\}}(\lfloor\frac{n}{T}\rfloor)\times(\lfloor\frac{m}{T}\rfloor)\times\sum_{d|T}d\times\mu(\lfloor\frac{T}{d}\rfloor) \\
&=\sum_{T=1}^{n}(\lfloor\frac{n}{T}\rfloor)^{2}\times\varphi(T) \\
\end{aligned}
\]
对于 task 7,\(n=m\) 让我们很方便地直接少了一个变量,然后就继续推
\begin{aligned}
&=\left(2\sum_{i=1}^{n}\sum_{j=1}^{i}\gcd(i,j)\right)-\frac{n(n+1)}{2} \\
&=\left(2\sum_{i=1}^{n}\sum_{d|i}d\times\sum_{j=1}^{i}[\gcd(i,j)=d]\right)-\frac{n(n+1)}{2} \\
&=\left(2\sum_{i=1}^{n}\sum_{d|i}d\times\sum_{j=1}^{\lfloor\frac{i}{d}\rfloor}[\gcd(\lfloor\frac{i}{d}\rfloor,j)=1]\right)-\frac{n(n+1)}{2} \\
&=\left(2\sum_{i=1}^{n}\sum_{d|i}d\times\varphi(\lfloor\frac{i}{d}\rfloor)\right)-\frac{n(n+1)}{2} \\
\end{aligned}
\]
然后
\]
后面的就是前面举的例子了,略。
/*
\large\text{For 1e6 part} \\
\sum_{i=1}^{n}\sum_{j=1}^{m}\gcd(i,j) \\
\sum_{d=1}^{\min(n,m)}d\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=d] \\
\sum_{d=1}^{\min(n,m)}d\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}[\gcd(i,j)=1] \\
\sum_{d=1}^{\min(n,m)}d\sum_{i=1}^{n/d}\sum_{j=1}^{m/d}\sum_{k|i,k|j}\mu(k) \\
\sum_{d=1}^{\min(n,m)}d\sum_{k|(n/d),k|(m/d)}\mu(k)(n/(dk))(m/(dk)) \\
\sum_{d=1}^{\min(n,m)}d\sum_{k|(n/d),k|(m/d)}\mu(k)(n/(dk))(m/(dk)) \\
\sum_{T=1}^{\min(n,m)}\sum_{d|T}d\times\mu(T/d)\times(n/T)\times(m/T) \\
\sum_{T=1}^{\min(n,m)}(n/T)\times(m/T)\times\sum_{d|T}d\times\mu(T/d) \\
\sum_{T=1}^{n}(n/T)^{2}\times\varphi(T) \\
\text{precalculate the last part} \\
\large\text{For 1e7 part} \\
n=m \\
\left(2\sum_{i=1}^{n}\sum_{j=1}^{i}\gcd(i,j)\right)-\frac{n(n+1)}{2} \\
\left(2\sum_{i=1}^{n}\sum_{d|i}d\times\sum_{j=1}^{i}[\gcd(i,j)=d]\right)-\frac{n(n+1)}{2} \\
\left(2\sum_{i=1}^{n}\sum_{d|i}d\times\sum_{j=1}^{i/d}[\gcd(i/d,j)=1]\right)-\frac{n(n+1)}{2} \\
\left(2\sum_{i=1}^{n}\sum_{d|i}d\times\varphi(i/d)\right)-\frac{n(n+1)}{2} \\
f(i)=\sum_{d|i}d\times\varphi(i/d) \\
\text{f(i) is able to be sieved;} \\
f(1)=1,f(p)=p-1+p=2\times p-1,f(p^{k})=(k+1)\times p^{k}-k\times p^{k-1}
*/
#include<cstdio>
#include<algorithm>
using namespace std;
int id,t,n,m,tag[10000010],prime[10000010],cnt;
long long f[10000010],phi[10000010];
long long cqpow(long long bas,int fur)
{
long long res=1;
while(fur)
{
if(fur&1) res*=bas;
bas*=bas;
fur>>=1;
}
return res;
}
void search(int x)
{
tag[1]=phi[1]=1;
for(int i=2;i<=x;++i)
{
if(!tag[i])
{
prime[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&(long long)prime[j]*i<=x;++j)
{
tag[prime[j]*i]=1;
if(i%prime[j]==0)
{
phi[prime[j]*i]=phi[i]*prime[j];
break;
}
else phi[prime[j]*i]=phi[i]*(prime[j]-1);
}
}
for(int i=1;i<=x;++i) phi[i]+=phi[i-1];
}
long long calc(int x,int y)
{
long long res=0;
int lim=min(x,y);
for(int l=1,r;l<=lim;l=r+1)
{
r=min(x/(x/l),y/(y/l));
res+=(long long)(n/l)*(m/l)*(phi[r]-phi[l-1]);
}
return res;
}
void exsearch(int x)
{
tag[1]=f[1]=1;
for(int i=2;i<=x;++i)
{
if(!tag[i])
{
prime[++cnt]=i;
f[i]=(i<<1)-1;
}
for(int j=1;j<=cnt&&(long long)prime[j]*i<=x;++j)
{
tag[prime[j]*i]=1;
if(i%prime[j]==0)
{
int tmp=i/prime[j],power=2;
while(tmp%prime[j]==0)
{
tmp/=prime[j];
power++;
}
if(tmp==1) f[prime[j]*i]=(power+1)*cqpow(prime[j],power)-power*cqpow(prime[j],power-1);
else f[prime[j]*i]=f[prime[j]*i/tmp]*f[tmp];
break;
}
else f[prime[j]*i]=f[prime[j]]*f[i];
}
}
for(int i=1;i<=x;++i) f[i]+=f[i-1];
}
long long excalc(long long x)
{
return (f[x]<<1)-((x*(x+1))>>1);
}
int main()
{
scanf("%d%d",&id,&t);
if(id^7)
{
search(1000000);
while(t--)
{
scanf("%d%d",&n,&m);
printf("%lld\n",calc(n,m));
}
}
else
{
exsearch(10000000);
while(t--)
{
scanf("%d%d",&n,&m);
printf("%lld\n",excalc(n));
}
}
return 0;
}
Note -「Maths」Euler 筛筛积性函数的更多相关文章
- P6222 「简单题」加强版 莫比乌斯反演 线性筛积性函数
LINK:简单题 以前写过弱化版的 不过那个实现过于垃圾 少预处理了一个东西. 这里写一个实现比较精细了. 最后可推出式子:\(\sum_{T=1}^nsum(\frac{n}{T})\sum_{x| ...
- hdu2421-Deciphering Password-(欧拉筛+唯一分解定理+积性函数+立方求和公式)
Deciphering Password Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
- Mobius反演与积性函数前缀和演学习笔记 BZOJ 4176 Lucas的数论 SDOI 2015 约数个数和
下文中所有讨论都在数论函数范围内开展. 数论函数指的是定义域为正整数域, 且值域为复数域的函数. 数论意义下的和式处理技巧 因子 \[ \sum_{d | n} a_d = \sum_{d | n} ...
- 积性函数&线性筛&欧拉函数&莫比乌斯函数&因数个数&约数个数和
只会搬运YL巨巨的博客 积性函数 定义 积性函数:对于任意互质的整数a和b有性质f(ab)=f(a)f(b)的数论函数. 完全积性函数:对于任意整数a和b有性质f(ab)=f(a)f(b)的数论函数 ...
- ACM-ICPC 2018 南京赛区网络预赛Sum,线性筛处理积性函数
SUM 题意:f(n)是n可以拆成多少组n=a*b,a和b都是不包含平方因子的方案数目,对于a!=b,n=a*b和n=b*a算两种方案,求∑i=1nf(i) 首先我们可以知道,n=1时f(1)=1, ...
- 莫比乌斯反演/线性筛/积性函数/杜教筛/min25筛 学习笔记
最近重新系统地学了下这几个知识点,以前没发现他们的联系,这次总结一下. 莫比乌斯反演入门:https://blog.csdn.net/litble/article/details/72804050 线 ...
- bzoj2693--莫比乌斯反演+积性函数线性筛
推导: 设d=gcd(i,j) 利用莫比乌斯函数的性质 令sum(x,y)=(x*(x+1)/2)*(y*(y+1)/2) 令T=d*t 设f(T)= T可以分块.又由于μ是积性函数,积性函数的约束和 ...
- hdu1452 Happy 2004(规律+因子和+积性函数)
Happy 2004 题意:s为2004^x的因子和,求s%29. (题于文末) 知识点: 素因子分解:n = p1 ^ e1 * p2 ^ e2 *..........*pn ^ en 因子 ...
- HDU 1452 Happy 2004 (逆元+快速幂+积性函数)
G - Happy 2004 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Subm ...
- spoj 3871. GCD Extreme 欧拉+积性函数
3871. GCD Extreme Problem code: GCDEX Given the value of N, you will have to find the value of G. Th ...
随机推荐
- GTX.Zip:一款可以替代 gzip 的基因大数据压缩软件
今天给大家推荐一款基因大数据压缩的大杀器:GTX.Zip. GTX.Zip 这款软件是由曾在 2016 年 GCTA 风云挑战赛中的那匹黑马--人和未来生物科技有限公司开发的,而当时他们也是打破了基因 ...
- VUE路由传参的实用方式
本文讲解了VUE项目中路由之间的传值方式,涉及到的方法都是开发时常用的,希望对大家有多帮助. 1. 方式一:使用router-link标签 1.1 params 传参 首先定义好路由 const ro ...
- 实用的windows快捷键
Alt+F4 关闭窗口 win+D 显示桌面 win+Tab 切换窗口 Alt+Tab 应用之间的切换 win+E 打开我的电脑 Ctrl+Shift+Esc 打开任务管理器 Home 回到行首 En ...
- jenkins中的坑_CreateProcess error=1392
环境:windows11,jdk1.8,jenkins_2.346.war 起因 最近在使用jenkins部署项目的时候,填写仓库的url地址时,发现填完后报500这个错误,于是我打开jenkins的 ...
- Docker化Spring Boot应用
本文翻译自国外论坛 medium,原文地址:https://medium.com/@bubu.tripathy/dockerizing-your-spring-boot-application-75b ...
- CMU15445 (Fall 2020) 数据库系统 Project#2 - B+ Tree 详解(下篇)
前言 上一篇博客中实现了单线程 B+ 树的查找.插入.删除和迭代操作,这篇博客将完成实验二的剩余任务:并发 B+ 树.实现 B+ 树并发访问最简单的方法就是在整棵树上加一把大锁,但是这样会导致过多线程 ...
- 深度Q网络:DQN项目实战CartPole-v0
摘要:相比于Q learning,DQN本质上是为了适应更为复杂的环境,并且经过不断的改良迭代,到了Nature DQN(即Volodymyr Mnih发表的Nature论文)这里才算是基本完善. 本 ...
- C# - XMLHelper :一个操作XML的简单类库
下午写了一个操作XML文件的类库,后来不用了,水篇文章存个档 整体功能 XMLHelper.cs主要提供以下功能: 加载XML文件:从文件路径或字符串中加载XML文档,并返回XmlDocument对象 ...
- 云享·案例丨打造数智物流底座,华为云DTSE助力物联云仓解锁物流新“速度”
摘要:华为云凭借领先的技术和快速响应的开发者支持服务,助力物联亿达实现云上资源高可用.提升系统安全性与稳定性,为物联亿达提供了扎实的数字化基础. 本文分享自华为云社区<云享·案例丨打造数智物流底 ...
- JVM之指针压缩
做java开发的同学一般都比较熟悉JVM,那么关于指针压缩这块内容是不是也了解呢,不熟悉的小伙伴往下看吧. 首先说明,本文涉及的JDK版本是1.8,JVM虚拟机是64位的HotSpot实现为准. ja ...