C - A Short problem(矩阵快速幂)

According to a research, VIM users tend to have shorter fingers, compared with Emacs users.
  Hence they prefer problems short, too. Here is a short one:
  Given n (1 <= n <= 10 18), You should solve for

g(g(g(n))) mod 10 9 + 7


  where

g(n) = 3g(n - 1) + g(n - 2)

g(1) = 1

g(0) = 0

Input

  There are several test cases. For each test case there is an integer n in a single line.
  Please process until EOF (End Of File).

Output

  For each test case, please print a single line with a integer, the corresponding answer to this case.

Sample Input

0
1
2

Sample Output

0
1
42837

题解:题目给出递推关系式:g[n]=3*g[n-1]+g[n-2],则可构造规律矩阵a如下

3    1

1    0

初始矩阵b

1    0

0    0

运用矩阵快速幂即可,注意考虑0,1特殊情况。

#include<iostream>
#include<cstring>
#include<stdio.h>
using namespace std;
typedef long long ll;
ll mod1=1000000007;
ll mod2=222222224;
ll mod3=183120;
ll a[3][3],b[3][3],c[3][3],n,ans;
ll f(ll n,ll mod)
{
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(c));
    a[1][1]=3,a[1][2]=1;
    a[2][1]=1,a[2][2]=0;
    b[1][1]=1;
    n--;
    while(n)
    {
        if(n&1)
        {
            memset(c,0,sizeof(c));
            for(int k=1; k<=2; k++)
            {
                for(int i=1; i<=2; i++)
                {
                    //if(a[i][k])
                    for(int j=1; j<=2; j++)
                    {
                        c[i][j]=(c[i][j]+a[i][k]*b[k][j])%mod;
                    }
                }
            }
            for(int i=1; i<=2; i++)
            {
                for(int j=1; j<=2; j++)
                {
                    b[i][j]=c[i][j];
                }
            }
        }
        memset(c,0,sizeof(c));
        for(int k=1; k<=2; k++)
        {
            for(int i=1; i<=2; i++)
            {
                for(int j=1; j<=2; j++)
                {
                    c[i][j]=(c[i][j]+a[i][k]*a[k][j])%mod;
                }
            }
        }
        for(int i=1; i<=2; i++)
        {
            for(int j=1; j<=2; j++)
            {
                a[i][j]=c[i][j];
            }
        }
        n>>=1;
    }
    return b[1][1];
}
int main()
{
    while(scanf("%lld",&n)!=EOF)
    {
        if(n==0||n==1)
        {
            cout<<n<<endl;
            continue;
        }
        ans=f(n,mod3);
        if(ans>=2)
            ans=f(ans,mod2);
        if(ans>=2)
            ans=f(ans,mod1);
        cout<<ans<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43824158/article/details/87636063