快速幂顾名思义,就是快速算某个数的多少次幂。其时间复杂度为 O(log₂N), 与朴素的O(N)相比效率有了极大的提高。
快速幂的原理比较好懂,就是说假如我们求的是3^11
,其实比较通用的办法就是
for 1:11
a*=3;
时间复杂度为O(n), 那么我们有没有更快的办法呢? 有的~就是下面要说的快速幂。
快速幂就是把指数进行一次log(N)级别的变换。11 = 2^3+2^1+2^0
那么我只需要算3^1
和3^2
还有3^8
这样复杂度就降下来了。算3^1
需要一次记为a
,把a
平方就是3^2
记为b
,把b
平方就是3^4
记为c
,再平方就是3^8
记为d
,这样把a b d
乘以之后就是结果了。这样速度就快起来了~
代码如下:
这个代码因为比较简单,所以很容易懂,下面的矩阵快速幂是我自己写的,可能会比较难~
int pow3(int a,int b)
{
int ans = 1,base = a;
while(b!=0)
{
if(b&1)
ans *= base;
base *= base;
b>>=1;
}
return ans;
}
矩阵快速幂是个很好玩的东西~ 为啥捏? 因为它能在Olog(N)级别的时间求的第N个斐波纳挈数列~叼不叼~(什么?你不知道什么是斐波纳挈。请百度~1 1 2 3 5 8...数列)
那是怎么实现呢?首先我们设立ans矩阵{1, 1; 1, 0}.然后这个矩阵就是类似上面的3
这个底数,然后直接矩阵相乘就可以了。
斐波纳挈数列是F(n) = F(n-1) + F(n-2)
,下面的代码是难一点的,F(n) = a*F(n-1) + b*F(n-2)
这个数列的,F(1) = F(2) = 1.
代码如下:
//
// main.cpp
// numberSequence_hdu
//
// Created by Alps on 14/12/22.
// Copyright (c) 2014年 chen. All rights reserved.
//
#include
using namespace std;
void multiMatrix(int ma[][2],int a, int b){
int i,j;
int cp[2][2] = {0,0,0,0};;
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
cp[i][j] = ((ma[i][0]*ma[0][j])%7 + (ma[i][1]*ma[1][j])%7)%7;
// printf("%d ",cp[i][j]);
}
// printf("\n");
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
ma[i][j] = cp[i][j];
}
}
}
void multiDoubleMatrix(int cp[][2], int ma[][2], int a, int b){
int temp[2][2];
int i,j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
temp[i][j] = ((cp[i][0]*ma[0][j])%7 + (cp[i][1]*ma[1][j])%7)%7;
}
}
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
cp[i][j] = temp[i][j];
}
}
}
int calculate(int ma[][2], int a, int b, int c){
if (c <= 0) {
return 1;
}
int cp[2][2] = {1,0,0,1};
while (c) {
if (c&1) {
multiDoubleMatrix(cp, ma, a, b);
}
multiMatrix(ma, a, b);
c = c>>1;
}
return (cp[0][0]+cp[0][1])%7;
}
int main(int argc, const char * argv[]) {
int a,b,c;
while (1) {
scanf("%d %d %d",&a,&b,&c);
int ma[][2] = {a%7,b%7,1,0};
// printf("%d %d %d %d\n",ma[0][0],ma[0][1],ma[1][0],ma[1][1]);
if (a == 0 && b == 0 && c == 0) {
break;
}
printf("%d\n",calculate(ma, a, b, c-2));
}
return 0;
}