nyoj--1000 又见斐波那契数列(快速幂+欧拉定理)

来源:互联网 发布:重庆网络干部学院 编辑:程序博客网 时间:2024/06/11 19:30

nyoj 1000

题解

F(0)=a,F(1)=b
F(n)=F(n1)F(n2)
F(n)=F(n2)2F(n3)
F(n)=F(n3)3F(n4)2
F(n)=F(n4)5F(n5)3

F(n)=F(1)f(n)F(0)f(n1)
F(n)=bf(n)af(n1)
f(n)正是斐波那契数列。
矩阵快速幂可以求出f(n)f(n1)的值。
然后快速幂计算bf(n)af(n1), 答案就是两者乘积。
需要注意一点,取模是对F(n)取模,不是f(n),那么问题来了,f(n)会是一个很大的数,如果不模一下根本存不下,怎么办呢?
这里的模 p=1000000007,是个素数,由欧拉定理,
ab%p=ab%(p1)%p
所以f(n)可以对 p1取模。

#include <iostream>#include <vector>#include <algorithm>using namespace std;typedef vector<int> vec;typedef vector<vec> mat;typedef long long ll;const int mod = 1000000007;// A*Bmat mul(mat& A, mat& B){    mat C(A.size(), vec(B[0].size()));    for(int i = 0; i < (int)A.size(); ++i)        for(int j = 0; j < (int)B[0].size(); ++j)            for(int k = 0; k < (int)B.size(); ++k)                C[i][j] = (C[i][j] + (ll)A[i][k] * B[k][j]) % (mod - 1);    return C;}// A^nmat pow(mat A, int n){    mat B(A.size(), vec(A.size()));    for(int i = 0; i < (int)A.size(); ++i) B[i][i] = 1;    while(n)    {        if(n & 1) B = mul(B, A);        A = mul(A, A);        n >>= 1;    }    return B;}// a^nint mypow(ll a, ll n){    ll res = 1;    while(n){        if(n & 1) res = (res * a) % mod;        a = (a * a) % mod;        n >>= 1;    }    return res;}void solve(int a, int b, int n){    mat A(2, vec(2));    A[0][0] = 1; A[0][1] = 1;    A[1][0] = 1; A[1][1] = 0;    A = pow(A, n);    int x = A[1][0], y = A[1][1];    cout << ((ll)mypow(b, x) % mod * mypow(a, y) % mod) % mod << endl;}int main(){    int a, b, n;    while(cin >> a >> b >> n)    {        solve(a, b, n);    }    return 0;}
0 0
原创粉丝点击