快速乘法(基於快速冪)


快速乘法的思想和快速冪的思想一樣,快速冪是求一個數的高次冪,快速乘法是求兩個數相乘,什么時候才用得到快速乘法呢,當兩個數相稱可能超過long long 范圍的時候用,因為在加法運算的時候不會超,而且可以直接取模,這樣就會保證數據超不了了。具體拿一個BestCoder的題目來示例。題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=5187

這個題先找規律,然后在求快速乘法和快速冪結合起來。題目推出來通式是:2n-2

推的過程就是一共有四種情況: 升升,升降,降升,降降,其中升升和降降最簡單,一共有兩種,復雜的就是升降和降升這兩種情況,首先來看降生,那么ai一定是最小值,因為兩邊都算ai了,所有當在第一個空的時候,前面一共有Cn-11, 后面就自動的確定了,在第二位的時候,有Cn-12, 同理到最后Cn-1n-2,所以加起來就是2n-1-2,這是降升,同理升降也是這么多,所以最后結果就是(2n-1-2) * 2 + 2 = 2n-2;下面就是快速冪了,由於題目給的n特別大,所以直接快速冪會超long long,看代碼:

#include<iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long LL;

LL fast_multi(LL m, LL n, LL mod)//快速乘法 
{
    LL ans = 0;//注意初始化是0,不是1 
    while (n)
    {
        if (n & 1)
            ans += m;
        m = (m + m) % mod;//和快速冪一樣,只不過這里是加 
        m %= mod;//取模,不要超出范圍 
        ans %= mod;
        n >>= 1;
    }
    return ans;
}
LL fast_pow(LL a, LL n, LL mod)//快速冪 
{
    LL ans = 1;
    while (n)
    {
        if (n & 1)
            ans = fast_multi(ans, a, mod);//不能直接乘 
        a = fast_multi(a, a, mod);
        ans %= mod;
        a %= mod;
        n >>= 1;
    }
    return ans;
}

int main()
{
    LL n, p;
    while (~scanf("%I64d %I64d", &n, &p))
    {
        if (n == 1)//特判一下 
        {
            printf("%I64d\n", 1 % p);
            continue;
        }
        printf("%I64d\n", (fast_pow(2, n, p) - 2 + p) % p);//這一步注意,不要為負數 
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM