1. 程式人生 > 實用技巧 >hdu4291 A Short problem - 矩陣快速冪 + 迴圈節

hdu4291 A Short problem - 矩陣快速冪 + 迴圈節

給出一個廣義斐波那契數列,求套娃後的值
這不是傻逼題嗎?來幾個迴圈節就行了
暴力求迴圈節

#include<cstdio>
#define ll long long
const ll MOD = 1e9 + 7;
int main() {
    ll a, b; // f[n] = (bf[n - 1] + af[n - 2]) % mod;
    a = 1;
    b = 3;
    for(ll i = 1; ; i++) {
        if(a == 0 && b == 1){
            printf("%lld\n", i);
            break;
        }
        ll c = (3 * b + a) % MOD;
        a = b, b = c;
    }
    return 0;
}

求出
1e9 + 7 的迴圈節 222222224
222222224 的迴圈節 183120
也就是說,最裡面那層的mod是183120,第二層是222222224,第三層是1e9+7

#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
const int N = 2;
struct Matrix{
    int n, m;
    ll a[N][N];
    Matrix(int n = 0, int m = 0):n(n),m(m){memset(a, 0, sizeof(a));}
};
Matrix mul(Matrix a, Matrix b, ll mod) {
    Matrix ans(a.n, b.m);
    for(int i = 0; i < a.n; i++) {
        for(int j = 0; j < b.m; j++) {
            for(int k = 0; k < a.m; k++) {
                ans.a[i][j] = (ans.a[i][j] + a.a[i][k] * b.a[k][j] % mod) % mod;
            }
        }
    }
    return ans;
}
Matrix ksm(Matrix a, ll b, ll mod){
    Matrix ans(a.n, a.m);
    for(int i = 0; i < max(a.n, a.m); i++) ans.a[i][i] = 1;
    while(b){
        if(b & 1) ans = mul(ans, a, mod);
        a = mul(a, a, mod);
        b >>= 1;
    }
    return ans;
}
ll f(ll n, ll mod){
    if(n == 0) return 0 % mod;
    if(n == 1) return 1 % mod;
    if(n == 2) return 3 % mod;
    Matrix base(2, 2);
    Matrix ans(2, 1);
    base.a[0][0] = 3, base.a[0][1] = 1;
    base.a[1][0] = 1, base.a[1][1] = 0;
    base = ksm(base, n - 2, mod);
    ans.a[0][0] = 3, ans.a[1][0] = 1;
    ans = mul(base, ans, mod);
    return ans.a[0][0];
}
int main(){
    ll n;
    while(~scanf("%lld", &n)) {
        ll ans = f(n, 183120);
        ans = f(ans, 222222224);
        ans = f(ans, 1e9 + 7);
        printf("%lld\n", ans);
    }
    return 0;
}