码迷,mamicode.com
首页 > 其他好文 > 详细

[矩阵快速幂+循环节]hdu4291

时间:2015-08-31 23:49:08      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:矩阵快速幂   循环节   

题意:
Given n (1 <= n <= 1018), You should solve for
g(g(g(n))) mod 109 + 7
  where
g(n) = 3g(n - 1) + g(n - 2)
g(1) = 1
g(0) = 0
分析:
这个递推关系可以用矩阵快速幂来解决,但是这个题的问题是mod很大,会爆long long 并且超时的。那么这就需要一些特技了。
于是看到大家都用的循环节,但是网上对为什么要这么取循环节却都模糊或者答非所问,大概都不太晓得,知道可以A提就可以了,或者是大神们觉得这些小儿科的东西不用提上来讲。我的理解是这是一个自变量与函数值之间的关系的一种利用吧,比如g(x)%mod, 随着g(x)的增大,总有一天会大过mod,然后又被变成0,重新开始,所以g(x)是循环的,它的循环节是mod,那么g(x)的变化是随着x的变化而变化的,那么g(x)循环,x 也会相应的有循环节(这是根据函数的性质来决定的,不是所有的函数都有循环节,起码这种类似斐波那契数列的函数可以),也就是说当x到达一个值n时,g(x)==mod,x大于n之后g(x)也大过mod,那么n+1和之前的1效果是一样的,所以x的循环节就是n. 在这个题中有多个循环节是因为函数的嵌套,那么最外层求得的自变量的循环节mod1就是里面嵌套函数的函数值的循环节,依次递推,找到三个循环节。

#include <iostream>
#include <cstdio>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
#define read freopen("q.in","r",stdin)
#define LL long long

LL mod ;
struct Matri
{
    LL mat[2][2];
    //Matri(){memset(mat,0,sizeof(mat));}
    void init()
    {
        mat[0][1]=mat[1][0]=0;
        mat[0][0]=mat[1][1]=1;
    }
};

Matri mul(Matri a,Matri b)
{
    Matri res;
    int i,j,k;
    for(i=0;i<2;i++)
    {
        for(j=0;j<2;j++)
        {
            res.mat[i][j]=0;
            for(k=0;k<2;k++)
            {
                res.mat[i][j]=(res.mat[i][j]+(a.mat[i][k]*b.mat[k][j])%mod)%mod;
            }
        }
    }
    return res;
}

Matri exp(Matri a,LL n)
{
    Matri res;
    res.init();
    if(n==0)return res;
    if(n==1)return a;
    while(n)
    {
        if(n&1)res=mul(res,a);

        a=mul(a,a);
        n>>=1;
    }
    return res;
}

int main()
{
    Matri B;B.mat[0][0]=3;B.mat[0][1]=1;B.mat[1][0]=1;B.mat[1][1]=0;
    // circle();
    // cout<<mod<<"??£í£í£í£í£í??"<<endl;
    LL n;
    while(~scanf("%I64d",&n))
    {
        if(n==0)
        {
            puts("0");
            continue;
        }
        if(n==1)
        {
            puts("1");
            continue;
        }
        mod=183120L;

        Matri res=exp(B,n-1);
        n=res.mat[0][0];
        if(n!=0 && n!=1)
        {
            mod=222222224L;
            res=exp(B,n-1);
            n=res.mat[0][0];
        }
        if(n!=0 && n!=1)
        {
            mod=1000000007L;
            res=exp(B,n-1);
        }
        cout<<res.mat[0][0]<<endl;
    }


}

版权声明:本文为博主原创文章,未经博主允许不得转载。

[矩阵快速幂+循环节]hdu4291

标签:矩阵快速幂   循环节   

原文地址:http://blog.csdn.net/u010582475/article/details/48140713

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!