一
线性筛主要讲下思想,埃氏筛法就是用所有质数标记所有倍数,这样的时间复杂度是 \(O(n\log n\log n)\),有两只 \(\log\)。可是我不想要 \(\log\),于是欧拉筛:
改进:存下质数表。对于每一个数,只标记自己与不超过自己最小质因子的数的乘积,对于质数表 \(2,3,5\),循环到 \(i=6\) 时,只筛去 \(6\times 2=12\) 而不筛去 \(6\times 3=18\),因为 \(18=6\times 3=2\times 3\times 3=2\times 9\),会被 \(9\) 筛去。也就是说,枚举质数表中的质数超过 \(i\) 的最小质因子没有必要,\(i\) 的最小质因子以后会与更大的合数相乘。
这样每个数只被它的最小质因子筛去一次。时间复杂度为 \(O(n)\)。
code:
bool isprime[100010];
int prime[1010],tot=0;
memset(isprime,1,sizeof(isprime));
isprime[1]=0;
for(int i=2;i<=100000;i++)
{if(isprime[i])prime[++tot]=i;for(int j=1;j<=tot&&prime[j]*i<=100000;j++){isprime[i*prime[j]]=0;if(i%prime[j]==0)break;}
}
二
\(\varphi(n)\) 表示 \(1\sim n\) 中,与 \(n\) 互质的数的个数。
怎么求 \(\varphi(n)\) 就容斥一下就好了。令 \(ans=n\),在 \(n\) 的所有因数中,把含有一个质因数的个数减去,把含有两个质因数的个数再加上......总之就是容斥。
那相当于这个式子:
然后按照展开式编码就可以求出单个 \(\varphi(n)\) 了。
int getPhi(int n)
{int ans=n;for(int i=2;i*i<=n;i++){if(n%i==0){ans=ans*(i-1)/i;while(n%i==0)n/=i;}}if(n>1)ans=ans*(n-1)/n;return ans;
}
时间复杂度:\(O(\sqrt n)\)
三
积性函数:当 \(\gcd(x,y)=1\) 时,\(f(x\times y)=f(x)\times f(y)\)。
欧拉函数时积性函数,证明不会写,跳了。
讲一下欧拉函数的几个性质:
首先先把计算式挂着:
设
则
性质一
若 \(n\) 是质数,\(\varphi(n)=n-1\)。
计算式易得。
性质二
若 \(n=p^k\),\(\varphi(n)=(p-1)p^{k-1}\)。
计算式易得。
性质三
若 \(q\) 是质数,且 \(q\mid n\),则 \(\varphi (nq) = q\varphi(n)\);若 \(q\) 是质数,且 \(q\nmid n\),则 \(\varphi(nq)=(q-1)\varphi(n)\)
计算式易得。
性质四
证明:若 \(m\) 与 \(n\) 互质,则 \(n\),\(m\) 之间没有相同的质因子。那么
性质五
直接分解质因数可证。
还有一些常用的积性函数:
设 \(d(n)\) 表示 \(n\) 的约数的个数,则 \(d(n)\) 是积性函数。
设 \(s(n)\) 表示 \(n\) 的所有约数的和,则 \(s(n)\) 是积性函数。
证明不想写,我懒。
所有积性函数都可以用欧拉筛在 \(O(n)\) 的时间猜出。
四
进行一个例题的讲。
回头再补累死了。