快速冪(整數快速冪+矩陣快速冪)
閒的無聊,總結一下快速冪的演算法,一直在用偏移運算子,現在試試多種方法:
快速冪就是求一個數的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 多個。 俗話說,桃李不言下自成蹊。 希望我的辛苦和努力能得到你的認可,並對你