例题10-1 UVA 11582 Colossal Fibonacci Numbers!巨大的斐波那契数列

题意不说了,紫书说的很清楚!

分析:

F(i) = f(i) mod n,发现是有规律的,就是有周期!

因此思路就很明确了:

1.先找到Fi的周期,因为一个n就对应一个不同的周期,但n不大 不超过1000,因此可以先打表!

2.在找到a^b是周期的第几个key ,这里可以快速幂,mod = T周期!

3.最后求F[key],因为最大是100W,所以提前打表就好了,但是想练练矩阵快速幂!,但是用矩阵快速幂错了好几次!

用矩阵快速幂需要注意几点:

1.这里的mod变了 变成n了因为是取模n嘛,所以%n,

2.通过矩阵快速幂求出的结果不一定是正确的,一定要在取模一次!(T T,坑死了。)


注意:

打表时,n要从2开始,因为1没意义,如果是1的话 一取模全是0,因此直接在输入时判断if(a == 0 || n == 1)cout  << "0\n";


代码如下:


#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
using namespace std;
typedef unsigned long long llu;
llu mod;
llu cyc[1005];
vector<llu>fib;
struct Mar{
   llu mat[2][2];
}E = {1,0,0,1},D = {0,1,1,1};
llu my_pow(llu a,llu n){
    llu ans =1;
    while(n){
        if (n & 1)
            ans = ((ans % mod) * (a % mod)) % mod;
        n/=2;
        a= ((a % mod)*(a%mod)) % mod;
    }
    return ans;
}
Mar mul(Mar a, Mar b){
    Mar ans={0,0,0,0};
    for (int i = 0; i <2; ++i)
        for (int j = 0; j < 2; ++j)
            for (int k = 0; k < 2; ++k)
                ans.mat[i][j] += ((a.mat[i][k]%mod) *( b.mat[k][j]%mod)) % mod;
    return ans;
}
Mar pow2(Mar a,llu n){
    Mar ans = E;
    while(n){
        if(n & 1)
            ans = mul(ans,a);
        n/=2;
        a=mul(a,a);
    }
    return ans;
}
int main()
{
    for (int n = 2; n <= 1000 ;++n){
        fib.clear();
        fib.push_back(0);
        fib.push_back(1);
        for (int i = 2; ; ++i){
            fib.push_back((fib[i-1]+fib[i-2]) % n);
            if (fib[i] == 1 && fib[i-1] == 0){
                cyc[n]=(llu)i-1;
                break;
            }
        }
    }
    llu h;
    cin >> h;
    while(h--){
        llu a,b,n;
        cin >> a >> b >> n;
        if (n == 1 || !a){cout << "0" <<endl;continue;}
        llu T = cyc[n];
        mod = T;
        llu key = my_pow(a,b);
        mod = n;
        llu fn = pow2(D,key).mat[0][1]%mod;
        cout << fn << endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值