快速冪:
舉個栗子;
想求3的13次方。
把13寫成二進制形式 1101
從右往左 如果第i位是1,就把它看成3的i次方
上邊就可以看成是3的1次方,3的4次方,3的8次方。
把這些乘起來,正好是3的13次方。
也就是說本來循環13次,現在循環4次就行了。
然後一個問題就是每一位上的3的i次方怎麼求,
這個可以在從右向左遍歷的時候設一個標示值,初值設爲1。每向左遍歷一位,標示值乘以自身。
這樣在遍歷第一位的時候,標示值是3,遍歷第二位的時候,標示值是9,遍歷第三位的時候,標示值是81….
問題解決。
代碼:
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#define ll long long
const int MOD=1e7+7;
using namespace std;
ll Get_ans(ll x, ll n)
{
ll ris = 1;
while(n > 0)
{
if(n & 1)
{
ris = (ris * x) % MOD;
}
x = (x * x) % MOD;
n >>= 1;
}
return ris;
}
int main()
{
ll x,n;
cin >> x >> n;
cout << Get_ans(x,n) << endl;
}
矩陣快速冪:
(以求斐波那契爲例 )
#include<iostream>
#include<algorithm>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<string>
#include<cmath>
using namespace std;
#define LL long long
struct mat
{
LL m[2][2];
mat(){memset(m,0,sizeof(m));}
};
mat cheng(mat a,mat b)
{
mat c;
for (int i=0 ;i<2; i++)
{
for (int j=0; j<2; j++)
{
for (int k=0; k<2; k++)
{
c.m[i][j]+=(a.m[i][k]*b.m[k][j])%10000;
}
}
}
return c;
}
mat zxc(mat a,LL b)
{
mat c;
c.m[0][0]=c.m[1][1]=1;
while (b!=0)
{
if(b&1)
c=cheng(c,a);
a=cheng(a,a);
b>>=1;
}
return c;
}
int main(void)
{
LL n;
while (cin>>n&&n!=-1)
{
mat one;
if(n==0)
{
cout<<0<<endl;
continue;
}
else if(n==1)
{
cout<<1<<endl;
continue;
}
one.m[0][0]=one.m[1][0]=one.m[0][1]=1;
one=zxc(one,n-1);
cout<<one.m[0][0]%10000<<endl;;
}
return 0;
}