思路:杜教筛

提交:\(2\)次

错因:\(\varphi(i)\)的前缀和用\(int\)存的

题解:

对于一类筛积性函数前缀和的问题,杜教筛可以以低于线性的时间复杂度来解决问题。

先要构造\(h=f*g\),并且\(h\)的前缀和易求,\(g\)的区间和易求。

具体地:

\[\sum_{i=1}^{n}h(i)=\sum_{i=1}^{n}\sum_{d|i}g(d)\cdot f(\frac{i}{d})$$ $$\sum_{i=1}^{n}h(i)=\sum_{d=1}^{n}g(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}f({i})
\]

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

\[\sum_{i=1}^{n}h(i)=\sum_{d=1}^{n}g(d)\cdot S(\lfloor\frac{n}{d}\rfloor)
\]

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

当我们对后面的式子进行整除分块时,求\(S(n)\)的复杂度为\(O(n^{\frac{2}{3}})\)

所以主要就是如何构造\(h\)和\(g\)

好吧直接说了:

\(\epsilon=\mu\cdot I\)

\(id=\varphi\cdot I\)



对于\(f(n)=\varphi(n)\cdot n^k=\varphi(n^{k+1})\)的一类方法:

\(id^{k+1}=f\cdot id^k\)

#include<cstdio>
#include<iostream>
#include<unordered_map>
#include<cmath>
#define ll long long
#define R register int
using namespace std;
namespace Luitaryi {
template<class I> inline I g(I& x) { x=0; register I f=1;
register char ch; while(!isdigit(ch=getchar())) f=ch=='-'?-1:f;
do x=x*10+(ch^48); while(isdigit(ch=getchar())); return x*=f;
} const int N=5000000,Inf=2147483647;
int T,n,cnt,p[N/4],mu[N+10];
ll phi[N+10];
bool v[N+10];
inline void PRE() { phi[1]=mu[1]=1;
for(R i=2;i<=N;++i) {
if(!v[i]) p[++cnt]=i,phi[i]=i-1,mu[i]=-1;
for(R j=1;j<=cnt&&i*p[j]<=N;++j) {
v[i*p[j]]=true;
if(i%p[j]==0) {
mu[i*p[j]]=0;
phi[i*p[j]]=phi[i]*p[j]; break;
} mu[i*p[j]]=-mu[i];
phi[i*p[j]]=phi[i]*(p[j]-1);
}
}
for(R i=1;i<=N;++i) mu[i]+=mu[i-1];
for(R i=1;i<=N;++i) phi[i]+=phi[i-1];
}
unordered_map<int,int> memmu;
unordered_map<int,ll> memphi;
inline ll s_phi(int n) {
if(n<=N) return phi[n];
if(memphi.count(n)) return memphi[n];
register ll ans=0;
for(R l=2,r;r<Inf&&l<=n;l=r+1) {
r=n/(n/l),ans+=(r-l+1)*s_phi(n/l);
} return memphi[n]=1llu*n*(n+1ll)/2ll-ans;
}
inline int s_mu(int n) {
if(n<=N) return mu[n];
if(memmu.count(n)) return memmu[n];
register ll ans=0;
for(R l=2,r;r<Inf&&l<=n;l=r+1) {
r=n/(n/l),ans+=(r-l+1)*s_mu(n/l);
} return memmu[n]=1ll-ans;
}
inline void main() {
PRE(); g(T); while(T--) {
g(n); printf("%lld %d\n",s_phi(n),s_mu(n));
}
}
} signed main() {Luitaryi::main(); return 0;}

2019.08.23

77

最新文章

  1. 无法启动此程序,因为计算机中丢失AdbWinApi.dll。尝试重新安装该程序以解决此问题
  2. android 内存不足的问题
  3. Javascript中appendChilid()内涵
  4. Java中单态设计模式
  5. 基于jquery 封装的 select 小控件,解决 IE6 7 8里 select 边框 高度 无法遮挡等问题
  6. &lt;input type=&quot;text&quot;&gt;和&lt;textarea&gt;的区别
  7. 洛谷P3802:小魔女帕琪
  8. [已解决]virtualBox安装CentOS-6.3-x86_64-bin-DVD1.iso为什么总是显示命令行界面
  9. MyEclipse 8.6 下载
  10. 4.3《想成为黑客,不知道这些命令行可不行》(Learn Enough Command Line to Be Dangerous)—链接到目录
  11. 获取天气预报API
  12. VB 获取文件版本
  13. MySQL open_files_limit相关设置
  14. Alpha冲刺报告(3/12)(麻瓜制造者)
  15. Python学习笔记系列——高阶函数(filter/sorted)
  16. Druid.io通过NiFi摄取流数据
  17. 把表单转成json,并且name为key,value为值
  18. 清空messages方法
  19. KVM虚拟机无法启动
  20. react native 热更新

热门文章

  1. Django之Form与ModelForm组件
  2. 文件操作之打开文件与读写文件——C语言
  3. 一个无法解析的外部命令and无法解析的外部符号
  4. 数据结构——java实现队列
  5. 1、Java基础:面向对象六大原则
  6. VisualSVN 关于权限(第1篇)
  7. redis集群安装2
  8. hashCode 及hashcode与equals的区别
  9. Java学习第四天之标识符与关键字
  10. 2.caffe初解