数论学习

前言

近来发现自己的数论知识需要进行补充,感觉自己相对别人落下了好多,所以打算写一篇博客,跟进一下自己的知识储备

正文

1.数论函数

数论函数,指定义域为正整数、陪域为复数的函数
f:Z+→Cf:\mathbb{Z^+}\rightarrow\mathbb{C}f:Z+C

  • Tip:常数函数也是数论函数
    我们通常用一个数字代表常数函数,比如111代表f(n)=1f(n)=1f(n)=1,xxx代表f(n)=xf(n)=xf(n)=x
2.加性函数

对于一个函数fff,如果对于gcd(a,b)=1gcd(a,b)=1gcd(a,b)=1满足f(ab)=f(a)+f(b)f(ab)=f(a)+f(b)f(ab)=f(a)+f(b),就称其为加性函数

3.常见加性函数
  • 质因子数
    ω(n)=∑p∣n1\omega(n)=\sum_{p|n}1ω(n)=pn1
    ppp为质数
    gcd(a,b)=1gcd(a,b)=1gcd(a,b)=1说明a,ba,ba,b没有相同的质因子,所以这是加性函数
  • 质因子之和
    a1(n)=∑p∣npa_1(n)=\sum_{p|n}pa1(n)=pnp
    ppp为质数
    证明同“相异质因子数”的证明
4.完全加性函数

对于一个函数fff,如果∀a,b\forall a,ba,b满足f(ab)=f(a)+f(b)f(ab)=f(a)+f(b)f(ab)=f(a)+f(b),就称其为完全加性函数

5.常见完全加性函数
  • 可相同质因子数
    Ω(n)=∑p∣nt\Omega(n)=\sum_{p|n}tΩ(n)=pnt
    ppp为质数,ttt为最大的整数满足pt∣np^t|nptn
    两数相乘,质因子数量可以直接合并
  • 可相同质因子之和
    a0(n)=∑p∣np∗ta_0(n)=\sum_{p|n}p*ta0(n)=pnpt
    ppp为质数,ttt为最大的整数满足pt∣np^t|nptn
    证明同“可相同质因子数”的证明
6.积性函数

对于一个函数fff,如果f(1)=1f(1)=1f(1)=1,且对于gcd(a,b)=1gcd(a,b)=1gcd(a,b)=1满足f(ab)=f(a)∗f(b)f(ab)=f(a)*f(b)f(ab)=f(a)f(b),就称其为积性函数

  • Tip:注意一定要满足f(1)=1f(1)=1f(1)=1,这个条件把函数f(x)=0f(x)=0f(x)=0这个函数排除了
    证明:
    ∵f(a)=f(a)∗f(1)\because f(a)=f(a)*f(1)f(a)=f(a)f(1)
    ∴f(a)∗(f(1)−1)=0\therefore f(a)*(f(1)-1)=0f(a)(f(1)1)=0
    ∴f(1)=1或f(a)=0\therefore f(1)=1或f(a)=0f(1)=1f(a)=0
7.常见积性函数
  • Euler’s totient function(欧拉函数)
    φ(n)\varphi(n)φ(n)表示[1,n][1,n][1,n]中与nnn互质的数个数
    φ(n)=n∗∏i=1k(1−1pi)\varphi(n)=n*\prod_{i=1}^{k}\left(1-\frac{1}{p_i}\right)φ(n)=ni=1k(1pi1)
    其中p1,p2……pkp_1, p_2……p_kp1,p2pknnn的所有质因数
    容易发现每个质因数pppφ(n)\varphi(n)φ(n)的贡献都是独立的,设ttt为最大的整数满足pt∣np^t|nptn,其贡献的乘积为:(p−1)∗pt−1(p-1)*p^{t-1}(p1)pt1
    所以φ(n)\varphi(n)φ(n)是积性函数
  • Möbius function(莫比乌斯函数)
    μ(n)={1,若n=1(−1)k,若n无平方数因数且n=p1∗p2⋅⋅⋅pk0,若n有平方数因数\mu(n)=\begin{cases} 1,\ \ \ \ \ \ \ \ 若n=1 \\ (-1)^k,若n无平方数因数且n=p_1*p_2···p_k\\ 0,\ \ \ \ \ \ \ \ 若n有平方数因数 \end{cases}μ(n)=1,        n=1(1)k,nn=p1p2pk0,        n
    这是一个比较清楚的定义,容易发现每个质因数pppμ(n)\mu(n)μ(n)的贡献都是独立的,设ttt为最大的整数满足pt∣np^t|nptn,其贡献的乘积为:{−1,若t=10,若t>1\begin{cases}-1,若t=1\\ 0,\ \ \ 若t>1 \end{cases}{1,t=10,   t>1
    所以μ(n)\mu(n)μ(n)是积性函数
  • divisor function(除数函数)
    σx(n)=∑d∣ndx\sigma_x(n)=\sum_{d|n}d^xσx(n)=dndx
    这个积性函数的证明也非常简单,每加入一个质因数pppσx(n)\sigma_x(n)σx(n)的贡献都是使值乘上一个定值,设ttt为最大的整数满足pt∣np^t|nptn,其贡献的乘积为∑i=0tpxi\sum_{i=0}^tp^{xi}i=0tpxi
    所以除数函数还有一个式子是
    σx(n)=∏p∑pj∣npxj\sigma_x(n)=\prod_{p}\sum_{p^j|n}p^{xj}σx(n)=ppjnpxj
    ppp为质数
    特殊的σx(n)\sigma_x(n)σx(n)有两个值得注意的情况
    σ0(n)\sigma_0(n)σ0(n)代表nnn的因数数量,也写作d(n)d(n)d(n)
    σ1(n)\sigma_1(n)σ1(n)代表nnn的因数之和,也写作σ(n)\sigma(n)σ(n)
8.完全积性函数

对于一个函数fff,如果f(1)=1f(1)=1f(1)=1∀a,b\forall a,ba,b满足f(ab)=f(a)∗f(b)f(ab)=f(a)*f(b)f(ab)=f(a)f(b),就称其为完全积性函数

9.常见完全积性函数
  • power function(幂函数)
    Idk(n)=nkId_k(n)=n^kIdk(n)=nk
    证明很容易Idk(a)∗Idk(b)=ak∗bk=(a∗b)k=Idk(a∗b)Id_k(a)*Id_k(b)=a^k*b^k=(a*b)^k=Id_k(a*b)Idk(a)Idk(b)=akbk=(ab)k=Idk(ab)
    特殊的Idk(n)Id_k(n)Idk(n)有两个值得注意的情况
    Id0(n)=1Id_0(n)=1Id0(n)=1,也写作1(n)1(n)1(n)或者是I(n)I(n)I(n)
    Id1(n)=nId_1(n)=nId1(n)=n,也写作Id(n)Id(n)Id(n)
  • Liouville function(刘维尔函数)
    λ(n)=(−1)Ω(n)\lambda(n)=(-1)^{\Omega(n)}λ(n)=(1)Ω(n)
    Ω(n)\Omega(n)Ω(n)是完全加性函数,所以λ(n)\lambda(n)λ(n)是完全积性函数
  • 单位函数
    ϵ(n)={1,n=10,n>1\epsilon(n)=\begin{cases}1,n=1\\0,n>1 \end{cases}ϵ(n)={1,n=10,n>1
    特殊的,ϵ(n)\epsilon(n)ϵ(n)有时也写作e(n)e(n)e(n)
    显然是完全积性函数
Dirichlet product(狄利克雷卷积)

两个数论函数f,gf,gf,g,他们的狄利克雷卷积为
(f∗g)(n)=∑d∣nf(d)∗g(nd)(f*g)(n)=\sum_{d|n}f(d)*g(\frac nd)(fg)(n)=dnf(d)g(dn)
相关性质:

  • 交换律:f∗g=g∗ff ∗ g = g ∗ ffg=gf
    根据定义式可得
  • 结合律:(f∗g)∗h=f∗(g∗h)(f ∗ g) ∗ h = f ∗ (g ∗ h)(fg)h=f(gh)
    展开
    ((f∗g)∗h)(n)=∑d∣n(f∗g)(d)∗h(nd)=∑d∣n(∑k∣df(k)∗g(dk))∗h(nd)=∑a∗b∗c=nf(a)∗g(b)∗h(c)\begin{aligned} ((f*g)*h)(n)&=\sum_{d|n}(f*g)(d)*h(\frac nd)\\ &=\sum_{d|n}(\sum_{k|d}f(k)*g(\frac dk))*h(\frac nd)\\ &=\sum_{a*b*c=n}f(a)*g(b)*h(c)\\ \end{aligned}((fg)h)(n)=dn(fg)(d)h(dn)=dn(kdf(k)g(kd))h(dn)=abc=nf(a)g(b)h(c)
    同理(f∗(g∗h))(n)=((g∗h)∗f)(n)=∑a∗b∗c=ng(a)∗h(b)∗f(c)(f ∗ (g ∗ h))(n)=((g*h)*f)(n)=\sum_{a*b*c=n}g(a)*h(b)*f(c)(f(gh))(n)=((gh)f)(n)=abc=ng(a)h(b)f(c)
    (f∗g)∗h=f∗(g∗h)(f ∗ g) ∗ h = f ∗ (g ∗ h)(fg)h=f(gh)
  • 分配律:f∗(g+h)=f∗g+f∗hf ∗ (g + h) = f ∗ g + f ∗ hf(g+h)=fg+fh
    证明:
    ((g+h)∗f)(n)=∑d∣n(g(d)+h(d))∗f(nd)=∑d∣ng(d)∗f(nd)+∑d∣nh(d)∗f(nd)=(f∗g)(n)+(f∗h)(n)=(f∗g+f∗h)(n)\begin{aligned} ((g+h)*f)(n)&=\sum_{d|n}(g(d)+h(d))*f(\frac nd)\\ &=\sum_{d|n}g(d)*f(\frac nd)+\sum_{d|n}h(d)*f(\frac nd)\\ &= (f ∗ g)(n) + (f ∗ h)(n)\\ &= (f ∗ g+ f ∗ h)(n)\\ \end{aligned}((g+h)f)(n)=dn(g(d)+h(d))f(dn)=dng(d)f(dn)+dnh(d)f(dn)=(fg)(n)+(fh)(n)=(fg+fh)(n)
  • 单位元 f∗ϵ=ff*\epsilon=ffϵ=f
    显然
  • f,gf,gf,g为积性函数,则f∗gf*gfg为积性函数,若f,gf,gf,g为完全积性函数,则f∗gf*gfg为完全积性函数
    证明:设F=f∗gF=f*gF=fg,要证的是F(ij)=F(i)∗F(j)F(ij)=F(i)*F(j)F(ij)=F(i)F(j)
    F(ij)=∑ab=ijf(a)∗g(b)F(ij)=\sum_{ab=ij}f(a)*g(b)F(ij)=ab=ijf(a)g(b)
    F(i)∗F(j)=(∑a0b0=if(a0)∗g(b0))∗(∑a1b1=jf(a1)∗g(b1))=∑a0a1b0b1=ij(f(a0)∗f(a1))∗(g(b0)∗g(b1))=∑a0a1b0b1=ijf(a0a1)∗g(b0b1)=F(ij)\begin{aligned} F(i)*F(j)&=\left(\sum_{a_0b_0=i}f(a_0)*g(b_0)\right)*\left(\sum_{a_1b_1=j}f(a_1)*g(b_1)\right)\\ &=\sum_{a_0a_1b_0b_1=ij}(f(a_0)*f(a_1))*(g(b_0)*g(b_1))\\ &=\sum_{a_0a_1b_0b_1=ij}f(a_0a_1)*g(b_0b_1)\\ &=F(ij) \end{aligned}F(i)F(j)=(a0b0=if(a0)g(b0))a1b1=jf(a1)g(b1)=a0a1b0b1=ij(f(a0)f(a1))(g(b0)g(b1))=a0a1b0b1=ijf(a0a1)g(b0b1)=F(ij)
常见的狄利克雷卷积式子
  • d=1∗1d=1*1d=11
    d(n)=∑d∣n1d(n)=\sum_{d|n}1d(n)=dn1
  • σ=Id∗1\sigma=Id*1σ=Id1
    σ(n)=∑d∣nd\sigma(n)=\sum_{d|n}dσ(n)=dnd
  • ϵ=μ∗1\epsilon=\mu*1ϵ=μ1
    ϵ(n)=∑d∣nμ(d)\epsilon(n)=\sum_{d|n}\mu(d)ϵ(n)=dnμ(d)
    证明:
    nnnkkk个相异质因子
    k=0k=0k=0,那么结果为111
    否则∑d∣nμ(d)=∑i=0k(−1)i(ki)=(1−1)k=0\begin{aligned} \sum_{d|n}\mu(d)&=\sum_{i=0}^k(-1)^i\dbinom{k}{i}\\ &=(1-1)^k\\ &=0 \end{aligned}dnμ(d)=i=0k(1)i(ik)=(11)k=0
  • φ=μ∗Id\varphi=\mu*Idφ=μId
    φ(n)=∑d∣nμ(d)nd\varphi(n)=\sum_{d|n}\mu(d)\frac ndφ(n)=dnμ(d)dn
    证明:
    首先证明:φ∗1=Id\varphi*1=Idφ1=Id

    ∑d∣nφ(d)=n\sum_{d|n}\varphi(d)=ndnφ(d)=n
    yangxin2003的形象证明
    给定一个nnn,枚举1n,2n⋅⋅⋅nn\frac 1n,\frac 2n···\frac nnn1,n2nn,并将每个约分
    考虑枚举约分后的分母(即枚举ddd),φ(d)\varphi(d)φ(d)即为ddd为分母时的最简分数数量,对应上面的nnn个数
    证完之后然后莫比乌斯反演(下面会提到)即可
Möbius inversion formula(莫比乌斯反演)

f=g∗1⇔g=u∗ff=g*1\Leftrightarrow g=u*ff=g1g=uf
另一种表示方式:
如果多项式f,gf,gf,g满足f(n)=∑d∣ng(d)f(n)=\sum_{d|n}g(d)f(n)=dng(d)
那么也一定满足g(n)=∑d∣nμ(d)f(nd)g(n)=\sum_{d|n}\mu(d)f(\frac nd)g(n)=dnμ(d)f(dn)
反之也成立
证明:
f=g∗1f=g*1f=g1
两边卷上μ\muμ
μ∗f=μ∗g∗1\mu*f=\mu*g*1μf=μg1
整理
μ∗f=ϵ∗g=g\mu*f=\epsilon*g=gμf=ϵg=g
g=μ∗fg=\mu*fg=μf
反过来同理

欧拉筛

每个数都只会被其最小的质因数筛到
复杂度Θ(n)\Theta(n)Θ(n),适合筛各种积性函数

inline void getlist(const int listsize)
{memset(isprime,1,sizeof(isprime));isprime[1]=0;for(rg int i=2;i<=listsize;i++){if(isprime[i]==1)prime[++primesize]=i;for(int j=1;j<=primesize&&(LL)i*(LL)prime[j]<=(LL)listsize;j++){isprime[i*prime[j]]=0;if(i%prime[j]==0)break;}}
}
  • Tip:对于欧拉筛有一个小技巧,可以开桶记录每个数的最小质因子,那么就可以做到Θ(n)\Theta(n)Θ(n)预处理,单次Θ(logn)\Theta(logn)Θ(logn)的质因数分解复杂度了
  • Tip:单次的分解质因数复杂度是Θ(n)\Theta(\sqrt n)Θ(n)的,枚举小于n\sqrt nn的数,如果整除就除掉,如果最后剩下的值不为1,那么剩下的这个值也是一个质因数,次数为1
杜教筛

现在有个数论函数f(n)f(n)f(n),现在要求S(n)=∑i=1nf(i)S(n)=\sum_{i=1}^nf(i)S(n)=i=1nf(i)
杜教筛的核心思想是:找到一个数论函数g(n)g(n)g(n)
因为显然满足∑i=1n∑d∣if(d)g(id)=∑i=1ng(i)S(⌊ni⌋)\sum_{i=1}^n\sum_{d|i}f(d)g(\frac id)=\sum_{i=1}^ng(i)S(\left\lfloor \frac ni\right\rfloor)i=1ndif(d)g(di)=i=1ng(i)S(in)
所以就有S(n)S(n)S(n)的递推式:
g(1)S(n)=∑i=1n(f∗g)(i)−∑i=2ng(i)S(⌊ni⌋)g(1)S(n)=\sum_{i=1}^n(f*g)(i)-\sum_{i=2}^ng(i)S(\left\lfloor \frac ni\right\rfloor)g(1)S(n)=i=1n(fg)(i)i=2ng(i)S(in)

  • Tip:能用杜教筛的前提是找到了合适的g(n)g(n)g(n),杜教筛能够筛某几种特定的积性函数,在下面会分别列举
常见杜教筛板子
  • φ(n)的前缀和S(n)\varphi(n)的前缀和S(n)φ(n)S(n)
    我们已经知道φ∗1=Id\varphi*1=Idφ1=Id
    那么在f=φf=\varphif=φ的条件下,g=1g=1g=1无疑是最佳选择,
    那么,上面的递推式就变成了
    S(n)=∑i=1ni−∑i=2nS(⌊ni⌋)S(n)=\sum_{i=1}^ni-\sum_{i=2}^nS(\left\lfloor \frac ni\right\rfloor)S(n)=i=1nii=2nS(in)
    首先证明这个递推式里的元素数量是Θ(n)\Theta(\sqrt n)Θ(n)
    解释:
    ∵⌊⌊xa⌋b⌋=⌊xab⌋∴所有被访问的元素为⌊ni⌋元素数是Θ(n)的设m=n这些元素是1,2⋅⋅⋅,m−1,m,⌊nm⌋,⌊nm−1⌋⋅⋅⋅,⌊n2⌋,⌊n1⌋\because\left\lfloor\frac {\left\lfloor\frac xa\right\rfloor}b \right\rfloor=\left\lfloor\frac x{ab} \right\rfloor\\ \therefore所有被访问的元素为\left\lfloor\frac ni \right\rfloor\\ 元素数是\Theta(\sqrt n)的\\ 设m=\sqrt n\\ 这些元素是1,2···,m-1,m,\left\lfloor\frac nm\right\rfloor,\left\lfloor\frac n{m-1}\right\rfloor···,\left\lfloor\frac n2\right\rfloor,\left\lfloor\frac n1\right\rfloorbax=abx访inΘ(n)m=n1,2,m1,m,mn,m1n,2n,1n
    然后考虑算法复杂度
    对于上面那个式子的第一项显然是(1+n)∗n2\frac {(1+n)*n}22(1+n)n,计算是Θ(1)的\Theta(1)的Θ(1)
    对于第二项,刚才已经证明⌊ni⌋\left\lfloor\frac ni \right\rfloorin的取值只有Θ(n)\Theta(\sqrt n)Θ(n)个,那么我们只要枚举每个取值,计算其贡献次数即可
    复杂度的式子是
    ∑i=1⌊n⌋Θ(i)+∑i=1⌊n⌋Θ(ni)\sum_{i=1}^{\left\lfloor \sqrt n\right\rfloor}\Theta(\sqrt i)+\sum_{i=1}^{\left\lfloor \sqrt n\right\rfloor}\Theta(\sqrt{\frac ni})i=1nΘ(i)+i=1nΘ(in)
    这个式子的结果是Θ(n34)\Theta(n^{\frac 34})Θ(n43)
    由于前面的n\sqrt nn个值可以用线性筛跑出来,所以复杂度为
    n+∑i=1⌊n⌋Θ(ni)\sqrt n+\sum_{i=1}^{\left\lfloor \sqrt n\right\rfloor}\Theta(\sqrt{\frac ni})n+i=1nΘ(in)
    瓶颈在后一半,所以可以通过调整块大小来优化复杂度
    设我们筛前kkk个,那么前面一项的复杂度为Θ(k)\Theta(k)Θ(k),后面一项的复杂度为Θ(nk)\Theta(\frac n{\sqrt k})Θ(kn)(这个的复杂度证明是根据微积分可得∑i=1nΘ(1i)=Θ(n)\sum_{i=1}^n\Theta(\frac 1{\sqrt i})=\Theta(\sqrt n)i=1nΘ(i1)=Θ(n),然后带入得Θ(n)∗Θ(nk)=Θ(nk)\Theta(\sqrt n)*\Theta(\sqrt {\frac nk})=\Theta(\frac n{\sqrt k})Θ(n)Θ(kn)=Θ(kn)),总复杂度最优时
    k=nk,k32=n,k=n23k=\frac n{\sqrt k},k^{\frac 32}=n,k=n^{\frac 23}k=kn,k23=n,k=n32
    最优复杂度为Θ(n23)\Theta(n^{\frac 23})Θ(n32)
    代码
#include
#include
#include
#include
#include
namespace fast_IO
{const int IN_LEN=10000000,OUT_LEN=10000000;char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}inline void flush(){fwrite(obuf,1,oh-obuf,stdout);}
}
using namespace fast_IO;
//#define getchar() getchar_()
//#define putchar(x) putchar_((x))
//#include
#define rg register
typedef long long LL;
template <typename T> inline T max(const T a,const T b){return a>b?a:b;}
template <typename T> inline T min(const T a,const T b){return a<b?a:b;}
template <typename T> inline void mind(T&a,const T b){a=a<b?a:b;}
template <typename T> inline void maxd(T&a,const T b){a=a>b?a:b;}
template <typename T> inline T abs(const T a){return a>0?a:-a;}
template <typename T> inline void swap(T&a,T&b){T c=a;a=b;b=c;}
//template  inline void swap(T*a,T*b){T c=a;a=b;b=c;}
template <typename T> inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);}
template <typename T> inline T lcm(const T a,const T b){return a/gcd(a,b)*b;}
template <typename T> inline T square(const T x){return x*x;};
template <typename T> inline void read(T&x)
{char cu=getchar();x=0;bool fla=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x;
}
template <typename T> inline void printe(const T x)
{if(x>=10)printe(x/10);putchar(x%10+'0');
}
template <typename T> inline void print(const T x)
{if(x<0)putchar('-'),printe(-x);else printe(x);
}
const int MAX=2000000;
bool isprime[MAX+1];
int n,prime[MAX+1],primesize;LL phi[MAX+1],phi1[MAX+1];
inline void getlist(const LL listsize)
{memset(isprime,1,sizeof(isprime));isprime[1]=0,phi[1]=1;;for(rg int i=2;i<=listsize;i++){if(isprime[i])prime[++primesize]=i,phi[i]=i-1;for(rg int j=1;j<=primesize&&(LL)i*prime[j]<=listsize;j++){isprime[i*prime[j]]=0;if(i%prime[j]==0){phi[i*prime[j]]=phi[i]*prime[j];break;}phi[i*prime[j]]=phi[i]*(prime[j]-1);}}
}
inline LL Val(const int x)
{if(x<=MAX)return phi[x];return phi1[n/x];
}
int main()
{getlist(MAX);for(rg int i=1;i<=MAX;i++)phi[i]+=phi[i-1];read(n);for(rg int i=min((int)sqrt(n),n/(MAX+1));i>=1;i--){const int u=n/i;LL res=(LL)u*(u+1)/2;int limit=sqrt(u);for(rg int j=1;j<=limit;j++)res-=Val(u/j);limit++;for(rg int j=1;limit*j<=u;j++)res-=phi[j]*((u/j)-(u/(j+1)));phi1[i]=res;}print(Val(n));return flush(),0;
}
  • μ(n)\mu(n)μ(n)的前缀和S(n)S(n)S(n)
    同样的,我们可以找到一个g(n)g(n)g(n),没错又是111,因为μ∗1=ϵ\mu*1=\epsilonμ1=ϵ
    所以带入式子S(n)=1−∑i=2nS(⌊ni⌋)S(n)=1-\sum_{i=2}^nS(\left\lfloor \frac ni\right\rfloor)S(n)=1i=2nS(in)
    哇,这不是东西更少了吗,和上面一样的思路,复杂度Θ(n23)\Theta(n^{\frac 23})Θ(n32)
    代码
#include
#include
#include
#include
#include
namespace fast_IO
{const int IN_LEN=10000000,OUT_LEN=10000000;char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}inline void flush(){fwrite(obuf,1,oh-obuf,stdout);}
}
using namespace fast_IO;
//#define getchar() getchar_()
//#define putchar(x) putchar_((x))
//#include
#define rg register
typedef long long LL;
template <typename T> inline T max(const T a,const T b){return a>b?a:b;}
template <typename T> inline T min(const T a,const T b){return a<b?a:b;}
template <typename T> inline void mind(T&a,const T b){a=a<b?a:b;}
template <typename T> inline void maxd(T&a,const T b){a=a>b?a:b;}
template <typename T> inline T abs(const T a){return a>0?a:-a;}
template <typename T> inline void swap(T&a,T&b){T c=a;a=b;b=c;}
//template  inline void swap(T*a,T*b){T c=a;a=b;b=c;}
template <typename T> inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);}
template <typename T> inline T lcm(const T a,const T b){return a/gcd(a,b)*b;}
template <typename T> inline T square(const T x){return x*x;};
template <typename T> inline void read(T&x)
{char cu=getchar();x=0;bool fla=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x;
}
template <typename T> inline void printe(const T x)
{if(x>=10)printe(x/10);putchar(x%10+'0');
}
template <typename T> inline void print(const T x)
{if(x<0)putchar('-'),printe(-x);else printe(x);
}
const int MAX=2000000;
bool isprime[MAX+1];
int T,n;
int prime[MAX+1],primesize;LL mu[MAX+1],mu1[MAX+1];
inline void getlist(const LL listsize)
{memset(isprime,1,sizeof(isprime));isprime[1]=0,mu[1]=1;for(rg int i=2;i<=listsize;i++){if(isprime[i])prime[++primesize]=i,mu[i]=-1;for(rg int j=1;j<=primesize&&(LL)i*prime[j]<=listsize;j++){isprime[i*prime[j]]=0;if(i%prime[j]==0){mu[i*prime[j]]=0;break;}mu[i*prime[j]]=-mu[i];}}
}
inline LL Val(const int x)
{if(x<=MAX)return mu[x];return mu1[n/x];
}
int main()
{getlist(MAX);for(rg int i=1;i<=MAX;i++)mu[i]+=mu[i-1];read(n);for(rg int i=min((int)sqrt(n),n/(MAX+1));i>=1;i--){const int u=n/i;LL res=1;int limit=sqrt(u);for(rg int j=1;j<=limit;j++)res-=Val(u/j);limit++;for(rg int j=1;limit*j<=u;j++)res-=mu[j]*((u/j)-(u/(j+1)));mu1[i]=res;}print(Val(n));return flush(),0;
}

其实代码差不太多

Min25筛

内容太多辣,可以看我另一篇博客Min_25筛学习Tip+链接
也是做积性函数前缀和的,并且能使得很多题目得到简化


我是分割线,目前要写的内容就这么多了,想到再更



本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部