HDU 4291 A Short problem // 矩阵快速幂, 循环节

来源:互联网 发布:淘宝商城冰箱价格 编辑:程序博客网 时间:2024/05/21 14:49

题目描述

HDU 4291 A Short problem

解题思路

题目大意:

g(n) = 3g(n1) + g(n2)
其中, g(0) = 0, g(1) = 1

g(g(g(n))) mod 1000000007

将递推关系变形为 : (g(n+1)g(n)) = (3 110)n (g(1)g(0))

然后用矩阵快速幂即可.
但是题目中有三重嵌套, 可能中间结果非常大, 导致效率低.既然涉及到取模操作,那么可能会存在循环节,我们可以先在本地找到这三个循环节.

typedef __int64 ll;ll getloop(ll mod){    ll g0 = 0, g1 = 1;    ll a = g0, b = g1, c;    for (ll i = 1;; ++i){        c = (3*b + a) % mod;        if (b == g0 && c == g1)            return i;        a = b;        b = c;    }}

参考代码

#include<stdio.h>int mod, m[3] = {183120, 222222224, 1000000007};//取模的循环节typedef __int64 ll;struct Matrix {    ll mat[2][2];};Matrix unit_matrix = {    1, 0,    0, 1};Matrix mul(Matrix a, Matrix b) {    Matrix res;    for(int i = 0; i < 2; i++)        for(int j = 0; j < 2; j++) {            res.mat[i][j] = 0;            for(int k = 0; k < 2; k++) {                res.mat[i][j] += a.mat[i][k] * b.mat[k][j];                res.mat[i][j] %= mod;            }        }    return res;}Matrix pow_matrix(Matrix a, ll n) {    Matrix res = unit_matrix;    while(n) {        if(n & 1)            res = mul(res, a);        a = mul(a, a);        n >>= 1;    }    return res;}int main() {    ll a, b, n;    Matrix tmp, p;    tmp.mat[0][0] = 3, tmp.mat[0][1] = 1;    tmp.mat[1][0] = 1, tmp.mat[1][1] = 0;    while(~scanf("%I64d", &n)) {        for (int i = 0;i < 3;++i){            mod = m[i];            p = pow_matrix(tmp, n);            n =  p.mat[1][0];        }        printf("%I64d\n",n);    }    return 0;}
0 0
原创粉丝点击