1. 程式人生 > >快速冪(整數快速冪+矩陣快速冪)

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

閒的無聊,總結一下快速冪的演算法,一直在用偏移運算子,現在試試多種方法:

快速冪就是求一個數的m次方的快速求法,因為正常情況下求次方可能就是一個數迴圈m次,然後乘一下,低次冪還好有一點,但是碰見高次的就不好辦了,比如:

求2的10次方,這個很好辦,for迴圈10次:

#include<stdio.h>            //可以,很簡單
int main()
{
	int i,mi=1;
	for(i=0;i<10;++i)
		mi=mi*2;
	printf("%d\n",mi);
}

但是碰見10000000次呢?比如2的100000000次冪怎麼辦。。迴圈肯定超時,因此我們可以曲線救國,運用快速冪比如:

原理:任何一個數都可以用二進位制進行表達,我們給他拆開看,一次判斷一位:

比如2的11次方:11用二進位制就是1011,分別是8*1+4*0+2*1+1*1,因此我們只用迴圈四次就好了,

四次的迴圈:

 第一次:0+1*1
第二次:1+2*1
第三次:3+4*0
第四次:3+8*1 

而不用迴圈11次,再舉個例子:2的100000次方:100000用二進位制表示是1 1000 0110 1010 0000,就是1*0+2*0+4*0+8*0+16*0+32*1+64*0+128*1+。。。

迴圈17次就行了,看100000次的迴圈縮減到了17次,是不是很好用?它是按照倍數來加的,因此就算爆int的數也只用32次就行了,感覺賊快,好了,廢話就不說了,我們為了實現這種方法,就要每次更換底數,也就是說每次的下面的數是上一次的平方。。。應該還好吧。

上程式碼。。。:(偏移運算子法)

#include<stdio.h>
#include<string.h>
#include<math.h>

#include<map>
#include<queue>
#include<stack>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;

#define ll long long
#define da    0x3f3f3f3f
#define xiao -0x3f3f3f3f
#define clean(a,b) memset(a,b,sizeof(a))//以上是雷打不動的標頭檔案23333 

int quick(int a,int n)		//快速冪 
{
	int can=a;			// 要求得底數 
	int ji=1;			//乘積 
	while(n)			//還有次冪 
	{
		if(n&1)
			ji=ji*can;	//如果這個地方是1,就乘上去,如果是0就不用乘 	//取模防爆int比如: ji=ji*can%1000000;
		can=can*can;		//每次的底數變平方 							//同理取模 			can=can*can%100000;
		n=n>>1;				//相當於每次右偏一次,每次除2 
	}
	return ji;
}

int main()
{
	int n,a;
	scanf("%d%d",&a,&n);	//a是底數,n是次冪 
	printf("%d\n",quick(a,n));//這樣如果數大了必定爆int,因此我們一般都取一下模,例如%100000 
	
}

矩陣快速冪:

與整數快速冪方法類似,只不過整數部分換成了矩陣相乘

實現程式碼:

#include<stdio.h>
#include<string.h>  
#include<math.h>  
  
#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<iostream>  
#include<algorithm>  
using namespace std;  

#define ll long long  
#define INF 0x3f3f3f3f  
#define mod 1000000007
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b) 
#define clean(a,b) memset(a,b,sizeof(a))// 水印 
//std::ios::sync_with_stdio(false);

ll temp[3][3],res[3][3],ans[3][3];

void matrix(ll a[][3],ll b[][3])
{
	clean(temp,0);//加一箇中間暫時存放資料的矩陣
	for(int i=1;i<3;++i)
	{
		for(int j=1;j<3;++j)
		{
			for(int k=1;k<3;++k)
				temp[i][j]=(temp[i][j]+a[i][k] * b[k][j])%mod;//矩陣相乘
		}
	}
	
	for(int i=1;i<3;++i)
	{
		for(int j=1;j<3;++j)
			a[i][j]=temp[i][j]%mod;//矩陣重新賦值
	}
}

void quick(ll n)
{
	/*
	矩陣快速冪
	[a,b,c,d] [a,b,c,d];
	[1,1,1,0] [1,1,1,0];
	[a*a+b*c , a*b+b*d , a*c+c*d , b*c+d*d]
	[1+1,1+0,1+0,1+0]  
	
	*/
	clean(ans,0);
	clean(res,0);
	res[1][1]=1;//初始矩陣,從三開始
	res[1][2]=1;
	res[2][1]=1;
	res[2][2]=0;
	for(int i=1;i<3;++i)//單位矩陣
	{
		for(int j=1;j<3;++j)
		{
			if(i==j)
				ans[i][j]=1;
			else
				ans[i][j]=0;
		}
	}
	//矩陣初始化
	while(n)
	{
		if(n&1)
			matrix(ans,res);//乘積
		matrix(res,res);
		n=n>>1;
	}
}

int main()
{
	ll n;
	cin>>n;
	for(int i=0;i<n;++i)
	{
		ll n;
        cin>>n;
        quick(n-2);//
        cout<<(ans[1][1]+ans[2][1])%mod<<endl;
		
		
	}
}

先就這了,後面的會不定期補更。。。

相關推薦

快速整數快速+矩陣快速

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

HDU-6395多校7 Sequence除法分塊+矩陣快速

review lse %d sca code left define hdu fin Sequence Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others

BZOJ4000 TJOI2015棋盤狀壓dp+矩陣快速

狀壓dp div out ons cstring char tdi getchar esp   顯然每一行棋子的某種放法是否合法只與上一行有關,狀壓起來即可。然後n稍微有點大,矩陣快速冪即可。 #include<iostream> #include<c

1005 Number Sequence長得像矩陣快速的找規律

A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. Given A, B, and n, you are to ca

【平安夜的胡策】訓練12.24複數預處理+矩陣快速+dp

這次比賽真是一言難盡,看來必須繼續努力。 這次比賽所有的“暴力”分就是170。 T1 題解: 喵喵喵在考場上看到這個題就mengbier了 首先你需要知道複數以及相關的運演算法

count 類插頭DP+矩陣快速

題目大意:有n個點,編號為1~n。第i個點和第j個點之間有一條無向邊當且僅當|i-j|<=k。求這個圖的生成樹個數。k≤5,n≤1015k≤5,n≤1015。 題目分析:Coming在他初二時的資料裡找到的一道題,是我校上古大神cdc給的。我不得不吐

【BZOJ1494】【NOI2007】生成樹計數動態規劃,矩陣快速

題面 Description 最近,小棟在無向連通圖的生成樹個數計算方面有了驚人的進展,他發現: ·n個結點的環的生成樹個數為n。 ·n個結點的完全圖的生成樹個數為n^(n-2)。這兩個發現讓小棟欣喜若狂,由此更加堅定了他繼續計算生成樹個數的 想法,他

【CF1151F】Sonya and Informatics動態規劃,矩陣快速

f11 表示 tor 快速 sizeof format oid 當前 ostream 【CF1151F】Sonya and Informatics(動態規劃,矩陣快速冪) 題面 CF 題解 考慮一個暴力\(dp\)。假設有\(m\)個\(0\),\(n-m\)個\(1\)。

2017省夏令營Day7 【快速,篩法,矩陣快速,線段樹】

swap 暴力 == define 練習 矩陣快速冪 color amp fine 題解:首先,我們可以得到一個規律:經過2次變換後,a和b的值都分別乘2了,所以只要用快速冪就能過啦,但是,要特判n為0的情況。 代碼如下: 1 #include<cstdi

POJ 3233 Matrix Power Series(求矩陣的和——分塊矩陣快速 or 二分遞迴+矩陣快速)

Matrix Power Series Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 21451 Accepted:

刷題記錄[SDOI2009]HH去散步動態規劃、矩陣快速乘、點邊互換思想

連結https://www.luogu.org/problemnew/show/P2151 題目描述 HH有個一成不變的習慣,喜歡飯後百步走。所謂百步走,就是散步,就是在一定的時間 內,走過一定的距離。 但是同時HH又是個喜歡變化的人,所以他不會立刻沿著剛剛走來的路走回。 又因為HH是個

輕量級MVVM框架Vue.js快速上手MVVM、SEO單頁面應用

靈活 vue.js 課程 基礎 har rip 完成 crud 通過 輕量級MVVM框架Vue.js快速上手(MVVM、SEO單頁面應用、×××服務器端渲染、Nuxt.js) 網盤地址:https://pan.baidu.com/s/1LkhepNpGAtRjrxp_CVJ

快速牛客 電音之王

不會寫。。。 記住板子吧。。 #include<stdio.h> #include<iostream> #include<math.h> #include<assert.h> using namespace std;

Hadoop基礎教程-第2章 Hadoop快速入門2.2 Hadoop下載與安裝

2.1 Hadoop下載與安裝2.1.1 官網下載可以使用迅雷或QQ旋風等多執行緒下載工具來下載,支援斷點續傳。成功下載後得到hadoop-2.7.3.tar.gz壓縮檔案,204M。請檢查壓縮包是否204M,瀏覽器下載的話可能會中斷。2.1.2 上傳至虛擬機器通過ll或ls命令可以檢視到已經上傳到虛擬機器n

七大排序演算法5------快速排序遞迴和非遞迴

         在本文中使用到的升序,降序,交換函式的程式碼見:這篇部落格 快速排序(遞迴實現) 快速排序的基本思想是在待排序序列中找到一個基準值(一般取待排序序列的最後一個元素),然後將該基準值放置在一個合適的位置,使得在基準值之前的元素都小於等於基準值,基準值之後的

經典排序演算法-快速排序挖坑法、前後指標法、基數排序

快速排序在實際應用中是比較表現好的排序演算法。快速排序我用兩種方法實現它。 第一種為方法,形象的稱為:挖坑法 基本思路:1、尋找pos位,然後將其分為兩段陣列,然後對這兩段陣列遞迴排序;      

Android開發快速入門環境配置、Android Studio安裝

Android是一種激動人心的開源移動平臺,它像手機一樣無處不在,得到了Google以及其他一些開放手機聯盟成員(如三星、HTC、中國移動、Verizon和AT&T等)的支援,因而不能不加以學習,否則你承擔不起為此付出的代價。 好在Android開發入門很容易,即使沒有Android手機都沒關係,只

快速排序Java隨機位置快排實現

package cn.edu.nwsuaf.cie.qhs; import java.util.Random; import java.util.Scanner; // public class QuickSort {     private int initArray[];     public i

div佈局快速入門徹底弄懂CSS盒子模式

前言 如果你想嘗試一下不用表格來排版網頁,而是用CSS來排版你的網頁,也就是常聽的用DIV來編排你的網頁結構,又或者說你想學習網頁標準設計,再或者說你的上司要你改變傳統的表格排版方式,提高企業競爭力,那麼你一定要接觸到的一個知識點就是CSS的盒子模式,這就是DIV排版的

ASP.NET Core 快速入門FineUICore + Razor Pages + Entity Framework Core

引子 自從 2009 年開始在部落格園寫文章,這是目前我寫的最長的一篇文章了。 前前後後,我總共花了 5 天的時間,每天超過 3 小時不間斷寫作和程式碼除錯。總共有 8 篇文章,每篇 5~6 個小結,總截圖數高達 60 多個。   俗話說,桃李不言下自成蹊。 希望我的辛苦和努力能得到你的認可,並對你