Java实现求解欧拉函数算法

欧拉函数

在数论,对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目(因此φ(1)=1)。此函数以其首名研究者欧拉命名(Euler’s totient function),它又称为Euler’s totient function、φ函数、欧拉商数等。 例如φ(8)=4,因为1,3,5,7均和8互质。 从欧拉函数引伸出来在环论方面的事实和拉格朗日定理构成了欧拉定理的证明。 欧拉函数-百度百科.

算法求解思想

欧拉函数具有以下性性质,以下性质是我们求解算法的依据:

  1. 当n=1时,n的欧拉函数Q(n)=1,n>1时,Q(n)的值位1~n之间与n互素的正整数个数
  2. 当n>1时,将n分解为素因数乘积的形式:n=p1t1p2t2…pktk,基于此,欧拉函数可表示为: Q ( n ) = n ∗ ∏ i = 1 k ( 1 − 1 p i ) Q(n)=n*\prod_{i=1}^k(1- \frac{1}{p_i}) Q(n)=ni=1k(1pi1)
  3. 设n为素数,设n=p,则Q(n)=p-1
  4. 若n=pm(p为素数,m>1),则Q(n)=pm-1(p-1)
  5. 若n=p*q(p,q均为素数),则Q(n)=(p-1)(q-1)
    本算法先将待求数进行素因式分解,利用HashMap进行因式去重,使用性质1和2来进行欧拉函数的求解。

代码

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;

public class EulerFunction {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int temp =(int)EulerGenerate(n);//由于double运算的精度很高(64位存储),所以误差很小,导致小数部分很小,可以直接舍弃小数部分
		System.out.println(temp);
	}

	private static double EulerGenerate(int n) {
		if(n==1) {
			return 1.0;
		}
		int eNum = -1;
		String[] dc = Discompose(n).split(" ");
		Map<Integer,Integer> map=new HashMap<>();//键表示素因数,值表示该素因数的次方数
		for (String child : dc) {
			int num=Integer.parseInt(child);//将每个素因数转化为整型(Discompose方法返回格式固定,略去异常处理)
			if(map.containsKey(num)) {
				map.put(num, map.get(num)+1);//把次方数加1
			}else {
				map.put(num, 1);
			}
		}
		//System.out.println(map);
		Set<Integer> set = map.keySet();
		double temp=1.0;
		for (Integer p : set) {
			temp=temp*(1-(1.0/p));//直接使用double代替分数近似运算,在主函数中采用舍弃法处理误差
		}
		temp*=n;
		return temp;
	}
	//对n进行素因式分解
	private static String Discompose(int n) {
		StringBuffer sb = new StringBuffer();
		for (int i = 2; i <= Math.sqrt(n); i++) {
			if (n % i == 0) {
				sb.append(i + " ");
				n = n/i;
				i--;
			}

		}
		sb.append(n+" ");
		return sb.toString();
	}
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值