1. 程式人生 > >快速乘法&快速冪&矩陣快速冪簡單講解

快速乘法&快速冪&矩陣快速冪簡單講解

快速冪演算法可謂是基礎但極其巧妙而優美並且非常有用的的一類演算法=w=

這裡介紹三種相關應用:1、快速乘法 2、快速冪 3、矩陣快速冪

一、整數運算

(a*b) mod c == ( (a mod c) * (b mod c) ) mod c

對於2進位制,2^n可用1後接n0來表示、

對於8進位制,可用公式 i+3*j == n (其中 0<= i <=2 ),

對於16進位制,可用 i+4*j==n0 <= i <=3)來推算,

表達形式為2^i 後接 j 0

1、a*b mod p(快速乘法)

當然,一定會有吃瓜群眾黑人問號臉,a*b直接算不接行了,快速乘法個鬼

==

其實大部分情況下確實是沒必要用快速乘法

But

乘法在計算機中的運算並沒有你想象中的那麼快,也要拆分成加法來做;

更常用的情況就是,在還沒取模的時候,a*b已經爆了int64long long),這時則顯然要用快速乘法了==,(因為在加法中不會超而且可以直接取模=w=

當然可能大家更熟悉的是快速冪,so ,這裡先介紹快速乘法(就這麼任性=A=

快速乘法的基本思想 ,是二進位制和乘法分配律的結合,

比如說,

7=(111)2  4*7=4*1112 

用分配律展開得 4*7 == 4*100+10+12

我們不難觀察出,快速冪可以通過判斷當前的位(bit)是1還是0,推斷出是否需要做求和操作,每次移動到下一位(

bit)時,就對ans進行*2操作,等待是否求和。

(這也可以看作是二分思想的應用)

這種演算法將b進行二分從而減少了不必要的運算=w=

時間複雜度是logn

=w=

function quick_power(a,b:int64):longint;//具體型別視題目而定
var
    ans:longint;
begin
   ans:=0;
   while (b<>0) do
   begin
      if (b and 1=1) then ans:=(ans+a) mod p;
      b:=b >>1;
      a:=(a+a) mod p;
   end;
   exit(ans);
end;


2、a^b mod p

快速冪其實可以看作是快速乘法的特例

在快速冪中,我們不再對ans進行*2操作,因為b已經從乘數變成了指數(人家已經升級了,而你如果還*2的話就out==),指數的相加意味著底數相乘,

But

二分的思想我們還是仍然繼續可以沿用的,把b轉化為2進位制數

這樣,我們就將原本用迴圈需要O(n)的演算法,改進為OlogN)的演算法。

=w=

var
        a,b,p,s:longint;
begin
    read(a,b,p);
    s:=1;
    while (b<>0) do
    begin
        if b mod 2=1 then s:=s*a mod p;
        b:=b >> 1;
        a:=a*a mod p;
    end;
    writeln(s);
end.


二、矩陣快速冪

由於考試中矩陣快速冪+矩陣乘法已經忘得跟不認識似的導致吃了10wa而被NM同學吐槽了一番==

矩陣的快速冪運算,其實思路和上面的整數快速冪是一樣的,對指數進行二分,只不過剛才的a是整型而現在變成了矩陣而已,所以唯一的區別就是剛剛簡單的 * ,如今要變成矩陣乘法的運算

矩陣快速冪的練習題可以去交一交CodevsFibonacci的一系列,用矩陣乘法+快速冪來優化Fibonacci可謂是經典中的模板題,多交幾次沒什麼壞處(我就在今天的考試中給跪了==

=w= 

下面是Codevs 1732 AC程式碼

const
    mo=1000000007;
var
    n                   :int64;
    f1,f2               :array[0..2,0..2] of longint;
    a,c                 :array[0..2] of longint;
procedure mul1;
var
    j,k:longint;
begin
   fillchar(c,sizeof(c),0);
   for j:=1 to 2 do
    for k:=1 to 2 do
      c[j]:=(c[j]+(a[k] mod mo) * (f1[k,j] mod mo) mod mo) mod mo;
   a:=c;
end;

procedure mul2;  
var
    i,j,k:longint;
begin
   fillchar(f2,sizeof(f2),0);
   for i:=1 to 2 do
    for j:=1 to 2 do
     for k:=1 to 2 do
      f2[i,j]:=(f2[i,j] +(f1[i,k] mod mo)*(f1[k,j] mod mo) mod mo) mod mo;
   f1:=f2;
end;

begin
   read(n);
   while not EOF do
   begin
      f1[1,1]:=0;f1[1,2]:=1;f1[2,1]:=1;f1[2,2]:=1;
      a[1]:=1;a[2]:=1;
      dec(n);
      while (n<>0) do //矩陣快速冪
      begin
         if (n mod 2<>0) then mul1;
         n:=n div 2;
         mul2;
      end;
      writeln(a[1]);
      read(n);
   end;
end.

                                            ——by Eirlys



轉載請註明出處=w=

相關推薦

快速乘法&快速&矩陣快速簡單講解

快速冪演算法可謂是基礎但極其巧妙而優美並且非常有用的的一類演算法=w= 這裡介紹三種相關應用:1、快速乘法 2、快速冪 3、矩陣快速冪 一、整數運算 (a*b) mod c == ( (a mod

矩陣乘法&&矩陣快速&&最基本的矩陣模型——斐波那契數列

pre gis uic printf 需要 數列 IT pac long 矩陣,一個神奇又令人崩潰的東西,常常用來優化序列遞推 在百度百科中,矩陣的定義: 在數學中,矩陣(Matrix)是一個按照長方陣列排列的復數或實數集合 ,最早來自於方程組的系數及常數所構成的方陣。這

整數快速乘法/快速+矩陣快速

快速乘法通常有兩類應用:一、整數的運算,計算(a*b) mod c 二、矩陣快速乘法 一、整數運算:(快速乘法、快速冪) 先說明一下基本的數學常識: (a*b) mod c == ( (a mod c) * (b mod c) ) mod c //這最後

快速+矩陣快速模板

#include<iostream> #include<cstring> #include<cmath> #include<cstdlib> #include<cstdio> #include<algorithm> #inc

快速模板【快速+矩陣快速

快速冪模板: 引入:就是將冪以二進位制數分解,比如5的6次方,6被分解為2,4,即110,110&1為0,不執行ans=ans*a%mod,但是a=a*a每迴圈一次就執行一次,現在a=5*5,下一次迴圈11&1==1,執行ans=1*25,a=25*25;1

矩陣快速(模版) 快速乘 + 快速 + 矩陣快速

矩陣快速冪:首先前置技能:  快速冪 + 矩陣乘法。 1  快速冪 1.1 快速乘法 1.1.1 引用自2009年國家集訓隊論文,駱可強:《論程式底層優化的一些方法與技巧》 (膜膜膜) 可以根據需要換成uLL   (unsigned long long)

,快速乘,快速,矩陣快速(求斐波那契數列)

快速冪: 方法一:: 首先快速冪有幾個公式: 1.(a^b)mod c=( a mod c)^b mod c; (ab) mod c=[(a mod c)*( b mod c)] mod c;    (積的取餘等於取餘的積取餘) 快速冪演算法依賴於一下兩個公式: a^b

快速,矩陣快速原理介紹

快速冪:複雜度為logn,比普通的n快了很多了. 原理 : 以求a的b次方來介紹: 首先把b轉換成二進位制數 該二進位制數第i位的權為 2^i - 1 . 比如 : 11的二進位制是101111 = 2³×1 + 2²×0 + 2¹×1 + 2º×

快速(整數快速+矩陣快速

閒的無聊,總結一下快速冪的演算法,一直在用偏移運算子,現在試試多種方法: 快速冪就是求一個數的m次方的快速求法,因為正常情況下求次方可能就是一個數迴圈m次,然後乘一下,低次冪還好有一點,但是碰見高次的就不好辦了,比如: 求2的10次方,這個很好辦,for迴圈10次: #

M斐波那契數列 (費馬小定理 + 二分快速 + 矩陣快速

M斐波那契數列F[n]是一種整數數列,它的定義如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 現在給出a, b, n,你能求出F[n]的值嗎? Input 輸入包含多組測試

快速快速 矩陣快速

求pow(a, exp)% mod 的值,快速冪其實也是利用了倍增的思想在裡面,比如求2^12 = 2^6 * 2^6 = 2^3 * 2^3 * 2^3 * 2^3 = 2 * 2^2 * 2 * 2^2 * 2 * 2^2 * 2 * 2^2 = 2 * 2 * 2 

快速+矩陣快速

ans 矩陣 位操作 .com www 二進制 class 平方根 color 一. 快速冪入門 相關博客: https://www.cnblogs.com/CXCXCXC/p/4641812.html https://www.cnblogs.com/vincent-

矩陣快速 模板與簡單講解

nbsp bsp 個數字 都是 例子 res class turn truct 模板 快速冪模板 1 void solve(matrix t,long long o) 2 { 3 matrix e; 4 5 memset(e.a,

UVA10870—Recurrences(簡單矩陣快速

src logs aps 矩陣 矩陣快速冪 分享 pow sizeof set 題目鏈接:https://vjudge.net/problem/UVA-10870 題目意思: 給出a1,a2,a3,a4,a5………………ad,然後算下面這個遞推式子,簡單的矩陣快速冪,裸題,

模板——矩陣快速+矩陣乘法

一個 ace 快速 應該 namespace cin ast c++ truct #include<bits/stdc++.h> using namespace std; const long long P=1e9+7; long long n,m;

Codeforces - 185A 簡單矩陣快速

inline size code void 矩陣 truct 明顯 amp source 題意:求第n個三角形內部的上三角形個數 對每個三角形分別維護上下三角形個數,記為\(dp[1][i],dp[2][i]\) 規律很明顯是 \(dp[1][i+1]=3*dp[1][i]

Codeforces Round #118 (Div. 2) :C (矩陣快速)類似與斐波那契+矩陣乘法

如圖: 就是求第n個圖形的上三角形的個數。 設f[n]為第n個圖形的上三角的個數 g[n]為第n個圖形的下三角的個數 則有: f[n]=3*f[n-1]+g[n-1]; g[n]=3*g[n-1]+f[n-1]; 可以用矩陣快速冪解決。 #include<iostr

矩陣乘法&矩陣快速

剛好在複習dp,順便把矩陣快速冪加速遞推給複習了。 首先矩陣乘法:f[i][j]=A[i][k]*B[k][j] 我們觀察斐波那契數列f[n]=f[n-1]+f[n-2],我們構造矩陣乘法 A:[ fn-2 fn-1] B:[0 1]     [1 1] C=A*

【學習筆記】快速+矩陣+矩陣乘法+矩陣快速

今天晚上我學習了矩陣 1、快速冪 通常,我們要算bpmodkbpmodk是這麼算的: ans := 1; for i := 1 to p do ans := ans * b mod k;

POJ-3735-Training little cats-構造矩陣+矩陣快速+稀疏矩陣乘法優化

http://poj.org/problem?id=3735 題意: n只貓,三種命令: 1、第i只貓吃掉所有花生; 2、第i只貓得到一個花生; 3、交換第i,j只貓的花生; 先由k個 這些命令組成一個操作序列 然後重複操作序列m次, n,k<=100,m<=1