快速冪

在這裏插入圖片描述


本題暴力解的話會超時。所應用的方法是快速冪,其主要思想是這樣的:比如求3^7
3^1 = 3;
3^2 = 9;
3^3 = 27;

這裏的3^3不是暴力算出來的,我們已經算出來了3^1 = 3和3^2 = 9;所以兩者相乘就是3^3。所以快速冪之所以快就是因爲,它利用了前面的結果,避免了重複計算。
下面我們需要考慮,怎麼樣才能讓計算機知道現在要用前面的那些結果呢?我們以3^5爲例講解,現在假設已經計算到3^5了,那麼我麼該用前面的哪些結果呢?
3^1 = 3;
3^2 = 9;
3^3 = 27;
3^4 = 81;
3^5 = 243;
我們既可以用3^1 * 3^4 = 81得到,也可以用3^2 * 3^3得到。而我們必須給計算機確定的指令。我們不妨把指數5分解,5 = 2^0 + 2^2.當然,你也可以分解爲其他底我們之所以以2爲底是考慮到計算機二進制的特性,可以天然的減少分解操作。5對應的二進制形式爲101,不難發現,二進制數制的表示上就是將有效位置爲1.從5的二進制裏可看出0和2位是有效位,正好滿足分解等式。 因此,我們只需把所有有效位相乘就可以得到結果。

#include<iostream>
using namespace std;

int main() {
	int a, b, p;
	cin >> a >> b >> p;
	int res = 1;
	while (b) {
		if (b & 1) res = res * 1ll * a%p;//b & 1取當前位,1ll強制轉化爲long long類型。
		a = a * 1ll * a%p;
	    b >>= 1;
	}
	cout << res << endl;
	return 0;
}

下面來一道練習題:在這裏插入圖片描述

不難發現,該題也是應用快速冪的思想,找有效位,快速冪是將有效位相乘,而快速和則是將有效位相加。

#include<iostream>
using namespace std;
typedef unsigned long long ULL;
int main() {
	ULL a, b, p;
	cin >> a >> b >> p;
	ULL res = 0;
	while (b) {
		if (b & 1) res = (res + a) % p;
		a = a * 2 % p;
		b >>= 1;
	}
	cout << res;
	return 0;
}
發佈了122 篇原創文章 · 獲贊 12 · 訪問量 9539
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章