今天是我在福州集訓的第六天,在今天,我學習了貪心和分治這兩種思想。我當然收貨了很多。但最令我受益的吧吧吧——就是快速冪了!要知道快速冪在2023年初賽中也是考到了!!也可見其的重要性!!
在學習快速冪之前,我們要知道一下問題:
q:快速冪是什麼?
a:快速冪是一種專門計算a^b%p的一種演算法,對於這種操作,快速冪是最好的。當然我們還會在下面具體解釋。
q:雖然快速冪很好用,但我們也要知道他在什麼地方用。如果連什麼時候用都不知道~那麼就算快速冪再厲害神仙也就不了你了呀~~
a:對於快速冪,我們一般在a^b%p中當b極大是使用。在b極大的時候普通的數是可以用暴力寫的,但是複雜度卻為o(b),當b極大是tle的可能性還是很大的。如果高精度的話,作取模運算未免又太麻煩了。所以一些偉大的大佬們就創造出了一種神奇的演算法——it means快速冪!他不僅**實現容易,而且時間複雜度優秀,為log級的,即使很大的數也能用非常快的時間做掉。
對於快速冪,我們有兩種實現的方法,一種是非遞迴演算法,另一種就是遞迴演算法(講了跟沒講似的。),那麼我們接下就會一一介紹。
兩種方法的例題都是a^b%p,求結果。(我們的約定:b在long long範圍內)(看到這資料有沒有絕望~~用暴力也會超時吧!但是我們用快速冪就能非常非常輕鬆的通過。)
一、非遞迴方法
我們首先可以將b轉化為乙個二進位制數,記x為當前二進位制位下的值(這樣講可能會有點抽象,接下來會具體說),在另記乙個數s為當前的值。演算法就是當遍歷到當前b二進位制位為1時,就s=s*x%p(注,mod p千萬不能忘,包括之前,為了保險可以再每部都mod 乙個p。當然不用模的時候千萬不能模,不然答案有可能是錯誤的。)
每次遍歷一次就將x=x*x一次(這裡不用判斷,而且是不能判斷當前位是否為1,因為x的值是跟當前的二進位制位是沒關係的)
接下來給乙個例子:
例如:2^8%10
那麼我們就按照剛剛的方法來模擬:
8二進位制展開後為1 0 0 0
x初值為a,即x=2;
s初值為1,即s=1;
①開始時遍歷到0,s不變,x=x*x%p=4;
②第二次遍歷到0,s不變,x=x*x%p=6
③第三次遍歷到0,s不變,x=x*x%p=6
④第四次遍歷到1,s=s*x%x=6,x=x*x%p=6;
遍歷完畢,結束。
因為這裡涉及到幼兒園奧數中的同餘問題,這裡就不詳細介紹了。
那麼這時可能會有人懷疑最後的結果到底對不對??那麼我們就用暴力演算法對拍一下。
暴力演算法為:2*2*2*2*2*2*2*2=256;
256 mod 10為6.
誒很驚喜!答案居然對了呢!
這就說明這方法是可行的。
那麼接下來就是**實現:
long longx=a,s=1;//初值(注意!這裡必須要long long 當p巨大時int是會炸的)
while (b!=0)//b還沒遍歷完+-86*86-+
emmmmmmmmmmm,這**也太短了吧~~應該是可以理解的!
二、遞迴法(二分法)
對於這種操作,我們就要從二分的角度去想。這使我們想到了冪的一種性質:a^x+y=a^x*a^y;那麼我們就很容易想到:我們可以將b拆分成b/2與b/2(對於偶數而言,對於奇數的話就在額外乘乙個a)。
如果我們將這個二分函式稱為f的話,就有以下公式:
b為偶數:f(a,b/2,p);
b為奇數:a*f(a,b/2,p);
那麼有了公式後,**實現就很容易了,**如下:
int f(int a,int b,int p)
reurn res;
}
那麼這就是快速冪的兩種方法,應該是好理解的吧~ Day6 快速排序
快速排序 快速排序使用分治的策略來把乙個序列為兩個子串行。快速排序又是一種分而治之思想在排序演算法上的典型應用。本質上來看,快速排序應該算是在氣泡排序基礎上的遞迴分治法。1.首先從數列中挑出乙個元素,稱為 基準 2.接著重新將數列排序,所有比基準小的元素擺放在基準的前面,所有比基準大的數都排在基準的...
演算法學習 Day6
實現乙個加法器,使其能夠輸出a b的值。輸入包括兩個數a和b,其中a和b的位數不超過1000位。可能有多組測試資料,對於每組資料,輸出a b的值。示例1 2 6 10000000000000000000 10000000000000000000000000000000 8 1000000000001...
演算法提高快速冪(快速冪演算法詳解)
問題描述 給定a,b,p,求 a b mod p。輸入格式 輸入共一行。第一行有三個數,n,m,p。輸出格式 輸出共一行,表示所求。樣例輸入 2 5 3 樣例輸出 資料規模和約定 共10組資料 對100 的資料,a,b為long long範圍內的非負整數,p為int內的非負整數。所謂的快速冪,實際上...