藍橋杯 歐拉函數 C++算法提高 HERODING的藍橋杯之路

資源限制
時間限制:1.0s 內存限制:256.0MB
問題描述
  老師出了一道難題,小醬不會做,請你編個程序幫幫他,獎金一瓶醬油:
  從1—n中有多少個數與n互質?
  |||||╭══╮ ┌═════┐
  ╭╯讓路║═║醬油專用車║
  ╰⊙═⊙╯ └══⊙═⊙═(坑爹的題面格式化,害得我用‘|’來代替空格,複製到記事本上看就變成正版的了)
輸入格式
  輸入共一行,表示一個整數n。
輸出格式
  輸出共一行,表示從1—n中與n互質的數的個數。
樣例輸入
30
樣例輸出
8
數據規模和約定
  60%的數據≤10^6
  100%的數據≤2*10^9

解題思路:
這道題目最關鍵的一點是使用歐拉函數!!!
如果你不用歐拉函數,而是通過for循環,從1到n分別判斷是否互爲質數(用輾轉相除法可以解決),那麼恭喜你,成功超時了!所以必須使用歐拉函數。
歐拉函數的思路很簡單,就是枚舉每一個數,如果是因子,則篩去所有該因子,並且減去有該因子的所有數。代碼如下(包括了我失敗的思路在內,不過註釋掉了):

#include<bits/stdc++.h>

using namespace std;

long long lcm(int m, int n){//輾轉相除法 
	if(m % n == 0){
		return n;
	}else{
		return lcm(n, m % n);
	}
}

int phi(int x){//注:ans即爲phi(x)的值
    int ans = x;//先令phi(x)=x,公式中的前部分
    for (int i = 2; i * i <= x; i ++){//枚舉每個數(注意,phi要求的因子是質數,而這裏枚舉的是所有數。至於爲什麼要這麼枚舉,請看代碼下邊的解釋)
        if(x % i == 0){//如果這個數是因子
            ans -= ans / i;//套公式x*(1-1/pi)=x-x/pi即這裏的ans-=ans/i;
            while(x % i == 0) x /= i;//篩去phi(x)中x的所有i因子
        }
    }
    if(x > 1)//篩後有剩餘的數,說明這個數也是一個質因子
        ans -= ans/x;//同理套公式
    return ans;//答案
}

int main(){
	long long n;
	int count = 0;
	cin >> n;
//	for(int i = 1; i < n; i ++){
//		if(lcm(n, i) == 1){
//			count ++;
//		}
//	}
	count = phi(n);
	cout << count;
	return 0;
} 

感謝這位老哥的思路:https://blog.csdn.net/DT2131/article/details/52116264

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章