[藍橋杯][演算法提高VIP]尤拉函式

一葉之修發表於2019-03-07

題目描述

給定一個大於1,不超過2000000的正整數n,輸出尤拉函式,phi(n)的值。 
如果你並不瞭解尤拉函式,那麼請參閱提示。 

提示 
尤拉函式phi(n)是數論中非常重要的一個函式,其表示1到n-1之間,與n互質的數的個數。顯然的,我們可以通過定義直接計算phi(n)。 
當然,phi(n)還有這麼一種計算方法。 
首先我們對n進行質因數分解,不妨設n=p1^a1  *  p2^a2  *  ...  *  pk^ak  (這裡a^b表示a的b次冪,p1到pk為k個互不相同的質數,a1到ak均為正整數),那麼 
phi(n)=n(1-(1/p1))(1-(1/p2))....(1-(1/pk)) 
稍稍化簡一下就是 
phi(n)=n(p1-1)(p2-1)...(pk-1)/(p1*p2*...*pk) 

計算的時候小心中間計算結果超過int型別上界,可通過調整公式各項的計算順序避免(比如先做除法)! 
 

輸入

在給定的輸入檔案中進行讀入: 
一行一個正整數n。 

輸出

將輸出資訊輸出到指定的檔案中: 
一行一個整數表示phi(n)。 

樣例輸入

17 

樣例輸出

16

 

原題連結

 

 尤拉函式:phi(n)=n(1-(1/p1))(1-(1/p2))....(1-(1/pk)) ;

                        p代表的是所有質因子(均不同)

                        例如16:因子有 2  4 6 8 16  其中質因子只有2 所以   phi(16)=n(1-(1/2))=8;

                        在例如

                    36:因子有2 3 6 12 36  其中質因子為2,3,phi(36)=n*(1-(1/2))*(1-(1/3))=12
注意事項:
                    因為可能爆int問題 所以n*(1-(1/p))可以轉化為n/p*(p-1);

對於大的資料儘量使用long

import java.util.Scanner;

public class 尤拉函式 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		long ans = n;
		for(int i=2;i*i<=n;i++) {//優化 O(sqrt(n)) 不過要在出口 if(n>1)ans/n*(n-1) O(n)不用
			if(n%i==0) {
				ans = ans/i*(i-1);////n*(1-(1/p))轉化為n/p*(p-1)
				while(n%i==0)
					n/=i;
			}
		}
		if(n>1)
			System.out.println(ans/n*(n-1));
		else
			System.out.println(ans);
	}

}

 

相關文章