快速幂的初步学习
快速幂的用处很多,常见的问题有快速幂取模和矩阵快速幂,一般的问题套用模板就可以。快速幂的思想是分治,类似于二分,所以时间复杂度是O(n)。
推荐一篇很好的文章:http://blog.csdn.net/cambridgeacm/article/details/7703809
FZU 1752 A^Bmoc C
题意:Given A,B,C, You should quickly calculate the result of A^B mod C. (1<=A,B,C<2^63).
分析:
直接明了的快速幂乘,但是由于a很大,所以需要计算a*b%c时,将b按二进制分解
(这题是以前写的)
#include <iostream>
#include <cstring>
#include<cstdio>
using namespace std;
typedef long long ll;
ll mul(ll a,ll b,ll c)//计算a*b%c,将b按二进制分解
{
ll res=0;
for(;b;b>>=1){
if(b&1){
res+=a;
while(res>=c)res-=c;
}
a<<=1;
while(a>=c)a-=c;
}
return res;
}
ll qmod(ll a,ll b,ll c)//幂乘,将b分解为2进制
{
ll res=1;
for(;b;b>>=1){
if(b&1)res=mul(a,res,c);
a=mul(a,a,c);
}
return res;
}
int main()
{
ll a,b,c;
while(scanf("%I64d%I64d%I64d",&a,&b,&c)!=EOF){
printf("%I64d\n",qmod(a%c,b,c));
}
return 0;
}
poj 3070 矩阵快速幂
题意:
给你n,求Fibonacci数列的第n项的后四位是多少?
分析:
由于这道题已经告诉你要用矩阵快速幂做了,而且给出了公式,所以直接快速幂就好。
一般的用到矩阵快速幂的题,会让你推出一个公式,然后化成矩阵的形式,用矩阵快速幂求解。
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int mod=10000;
const int N = 2;
struct Mat {
int mat[N][N];
};
int n=2, m;
int A,B;
Mat mul(Mat a, Mat b) {
Mat c;
memset(c.mat, 0, sizeof(c.mat));
int i, j, k;
for(k = 0; k < n; ++k) {
for(i = 0; i < n; ++i) {
for(j = 0; j < n; ++j) {
c.mat[i][j] += a.mat[i][k] * b.mat[k][j];
c.mat[i][j]%=mod;
}
}
}
return c;
}
Mat qmod(Mat a, int k) {
Mat c;
int i, j;
for(i = 0; i < n; ++i)
for(j = 0; j < n; ++j)
c.mat[i][j] = (i == j);
for(; k; k >>= 1) {
if(k&1) c = mul(a,c);
a = mul(a,a);
}
return c;
}
int main()
{
int n;
while(~scanf("%d",&n)){
if(n==-1)break;
Mat a;
a.mat[0][0]=a.mat[0][1]=a.mat[1][0]=1;;
a.mat[1][1]=0;
Mat c=qmod(a,n);
printf("%d\n",(c.mat[0][1])%mod);
}
return 0;
}