1. 程式人生 > >數論.快速冪

數論.快速冪

公式求冪→二分求冪→快速求冪→快速求冪取模 

公式求冪

         直接使用C語言的庫函式pow(),pow()函式在math標頭檔案裡

當然用公式求解,似乎很簡單,但是它的時間複雜度較高,為O(n),對於資料較大的問題,十分容易超時

二分求冪

二分冪的時間複雜度相較於第一種有了明顯的優化,達到了O(lgn)

二分求冪的原理可以用下面這張圖表示 

用遞迴來實現:

int pow(int a,int n)//返回值是a的n次方

{

    if(n==0)//遞迴終止條件

        return 1;

    if(n==1)

        return a;

    int result=pow(a,n/2);//二分遞迴

    result=result*result;//這部分奇數偶數都一樣

    if(n%2==1)//如果n是奇數,就要多乘一次

        result=result*a;

    return result;

}

用非遞迴來實現:

int pow(int a,int n)//返回值是a的n次方

{

    int result=1;

    while(n!=0)

    {

        if(n%2==1)//如果n是奇數

            result=result*a;//就要多乘一次

        a=a*a;

        n=n/2;//二分

    }

    return result;

}

快速冪

    快速冪是一種利用b的二進位制特徵來快速求a^b的演算法,藉助了強大的位運算,時間複雜度進一步優化,達到O(logN)

例如:求a11次方 
11的二進位制是1011 
11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1 

用非遞迴的程式碼實現

int pow(int a,int n)//返回值是an次方

{

    int result=1,flag=a;

    while(n!=0)

    {

        if(n&1)//如果n是奇數,即

n的二進位制最末位為1

            result=result*flag;

        flag=flag*flag;

        n=n>>1;//n的二進位制右移一位,即n/2

    }

    return result;

}

快速求冪取模

刷題中讓直接求冪的不多,求冪後取模的卻不少,畢竟求冪結果太大了。 
水平所限,只會用二分冪取模,時間複雜度與二分冪一樣O(lgn) 
基本可以在各種比賽中順利通過,也是目前比較常用的方法

原理同樣很簡單,都是小學學過的:積的取餘等於取餘的積取餘 (涉及到同餘定理)
接下來用程式碼實現

int pow(int a,int n,int b)//返回值是an次方對b取餘後的值

{

    int result=1;

    a=a%b;//積的取餘等於取餘的積取餘

    while(n>0)

    {

        if(n%2==1)

            result=result*a%b;//n是奇數的話就要多乘一次,原理和前面的二分求冪一樣

        n=n/2;//二分

        a=a*a%b;//積的取餘等於取餘的積取餘

    }

    return result;

影響計算機效率的是運算次數,而不是運算結果。 
所以前面幾個演算法都是通過增大運算結果,減少運算次數,提高計算機效率。