欧拉函数+欧拉线性筛

欧拉定义

百度的定义就不copy了 简单的说就是给定一个正整数n 小于n的正整数与n互质的个数 例如phi[8]=4 (1,3,5,7与8互质)
代码主要是用其公式


其中x是要求的数 n是x进行唯一分解定理后的不同pi的个数 pi是唯一分解定理后的数字(ex 20=2^2*5 那么p就有两个值 2和5) 敲重点 唯一分解定理


欧拉性质

欧拉函数是积性函数:*当a,b互质的时候(gcd(a,b)=1) , phi[a*b]=phi[a]phi[b]


欧拉函数优化算法代码

#include<iostream>
#include<algorithm>
#include<cstring>
#define maxn 1000
#define ll long long
using namespace std;
int oula_youhua(int n){
    
    
	int rea=n;//rea相当于公式中的x(将其 ∏分开存储每次乘之后的值) 
	for(int i=2;i*i<=n;i++){
    
    //i*i<=n优化 nlogn复杂度 
		if(n%i==0){
    
    //当找到第一个素数的时候 
			rea=rea-rea/i;//rea乘一下更新 (就是套公式) 
			do{
    
    //并且消除n中所有i的影响 并且继续寻找下一个唯一分解定理质数 
				n/=i;
			}while(n%i==0);
		}
		
	}
	if(n>1)//当结束后 特殊处理最后一个数 
	rea=rea-rea/n;
	return rea; 
	
} 


int main(){
    
    
	while(1){
    
    
		int x;
		cin>>x;
		cout<<oula_youhua(x)<<endl;
	}	
	return 0;
}

欧拉线性筛 O(n)

#include<iostream>
#include<algorithm>
#define maxn 1000
using namespace std;
int phi[maxn];
int prime[maxn];
int isprime[maxn<<2];
int tot=0;
void getphi(){
    
    //就是在素数筛的操作 
	for(int i=2;i<maxn;i++){
    
    
		if(!isprime[i]){
    
    
			prime[tot++]=i;
			phi[i]=i-1;//如果为素数 那么个数就是i-1个 
		}
		for(int j=0;j<tot;j++){
    
    //遍历目前的素数 
			if(i*prime[j]>maxn)break;//如果大于范围退出 
			isprime[i*prime[j]]=1;//标记素数 
			if(i%prime[j]==0){
    
    //如果这个数和素数有约数的话  phi更新(因为有约数 有公式可得 从两个数之间提出公共因子prime 乘以phi【】更新) 
				phi[i*prime[j]]=phi[i]*prime[j];// 由于公式x∏(1-1/pi) 可以提出来值  
				break;	
			}
			phi[i*prime[j]]=phi[i]*phi[prime[j]];//如果没有约数 那么i和prime就是相对素数由于性质gcd(a,b)==1 → phi[a*b]=phi[a]*phi[b] 
	}
	}	
}

int main(){
    
    
getphi();
phi[1]=1;	
for(int i=1;i<10;i++){
    
    
	cout<<phi[i]<<endl;
}
	return 0;
}

蒟蒻今天终于补了集训的第一篇博客

说到底还是一条懒狗 落泪.jpg

猜你喜欢

转载自blog.csdn.net/Stydwn/article/details/99671362