您的位置:首页 > 其它

线性筛及线性递推欧拉函数

2018-10-14 23:27 197 查看

首先是很常用的线性筛代码:

#define N 1000000
int n, cnt, vis[N+5], prime[N+5];
void sieve() {
vis[1] = 1;
for(int i = 2; i <= n; ++i) {
if(!vis[i]) prime[++cnt] = i;
for(int j = 1; j <= cnt && i*prime[j] <= n; ++j) {
vis[i*prime[j]] = 1;
if(i%prime[j]==0) break;
}
}
}

线性筛保证了每个合数只会被它的最小质因子筛掉,所以复杂度是近似\(O(n)\)的。

欧拉函数

定义:对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目(φ(1)=1)。
计算公式:

\(\phi(x)=x\prod\limits_{i=1}^{n}(1-\frac{1}{p_i})\)

其\(p_i\)为\(x\)的质因子。
性质:欧拉函数是积性函数(即\(\phi(mn)=\phi(m)\phi(n)\),m,n互质)
我们考虑怎样在线性筛时顺便求出欧拉函数:
1.若\(vis[i]=1\),说明\(i\)是质数,\(phi[i]=i-1\)
2.若\(prime[j]\)整除\(i\),说明\(i*prime[j]\)标准分解式中\(prime[j]\)的次数已经大于\(1\)了,根据欧拉函数的计算式,不难得出\(phi[i*prime[j]]=phi[i]*prime[j]\)
3.若\(prime[j]\)不整除\(i\),说明\(i\)与\(prime[j]\)互质,又因为\(prime[j]\)是质数,则\(phi[i*prime[j]]=phi[i]*phi[prime[j]]\),进而推出\(phi[i*prime[j]]=phi[i]*(prime[j]-1)\)
我们按照上式把线性筛改造一下就行了:

#define N 1000000
int n, cnt, vis[N+5], prime[N+5], phi[N+5];
void sieve() {
vis[1] = phi[1] = 1;
for(int i = 2; i <= n; ++i) {
if(!vis[i]) prime[++cnt] = i, phi[i] = i-1;
for(int j = 1; j <= cnt && i*prime[j] <= n; ++j) {
vis[i*prime[j]] = 1;
if(i%prime[j]==0) { phi[i*prime[j]] = phi[i]*prime[j]; break; }
phi[i*prime[j]] = phi[i]*phi[prime[j]];
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: