您的位置:首页 > 其它

hdu4549 斐波那契数列(乘法递推) + 欧拉定理 (快速幂,模幂)

2015-08-01 17:13 399 查看
这题的话,看a ,b 的指数,刚好可以使用斐波那契数列求解。
加法斐波那契数列是直接在最后用(b*m.mat[0][0] + a * m.mat[1][0] ) % MOD
乘法就变成了乘方!!所以需要用到快速模幂。。

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">然后用矩阵做。</span>


A^B %C 这题的C是质素,而且A,C是互质的。
所以直接A^(B%(C-1)) %C

比较一般的结论是 A^B %C=A^( B%phi(C)+phi(C) ) %C B>=phi(C)

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <iomanip>

using namespace std;
#define MOD 1000000007
#define N 2

struct Mat
{
long long mat

;
};

Mat operator * (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)
{
if(a.mat[i][k] <= 0)  continue;   //(针对ZOJ2853)剪枝,cpu运算乘法的效率并不是想像的那么理想(加法的运算效率高于乘法,比如Strassen矩阵乘法)
for(j = 0; j < N; ++j)
{
if(b.mat[k][j] <= 0)    continue;    //剪枝
c.mat[i][j] = (c.mat[i][j] + (a.mat[i][k] * b.mat[k][j]) % (MOD - 1)) % (MOD - 1);
}
}
}
return c;
}

Mat operator ^ (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 = c*a;
a = a*a;
}
return c;
}

long long Pow(long long n ,long long m, int mod)
{
long long res = 1;
while(m >= 1)
{
if(m & 1)
{
res = (res * n ) % mod;
}
n = n * n % mod ;
m >>= 1;
}
return res;
}

int main()
{
int a , b , n;
while(cin >> a >> b >> n)
{
Mat m;
m.mat[0][0] = 1;
m.mat[0][1] = 1;
m.mat[1][0] = 1;
m.mat[1][1] = 0;
if(n > 1)
{
m = m ^ (n - 1);
/*   for(int i = 0; i < N; ++i)
{
for(int j = 0; j < N; ++j)
cout << m.mat[i][j] <<" ";
cout << endl;
}
*/
cout <<(Pow( b , m.mat[0][0] , MOD )% MOD * Pow( a , m.mat[1][0] , MOD ) )%MOD << endl;
}
else if(n == 0) cout << a << endl;
else cout << b << endl;
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: