hdu 4291 A Short problem(矩阵+取模循环节)
A Short problem
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1785 Accepted Submission(s): 651
Problem Description
  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 <= 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 
Hence they prefer problems short, too. Here is a short one:
Given n (1 <= n <= 1018), You should solve for
where
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).
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
矩阵非常easy构造
矩阵A
1   0
0   0
递推矩阵B
3   1
1   0
g(n)=A*B^(n-1)的第1行第1列。
如今是一个多重函数在最外层取模,n为10^18,当到最外层取模肯定不能够,这时候就要寻找循环节了。首先是最
外层的模。通过暴力判循环节
long long x3, x1=0,x2=1;
     long long temp=1000000007;
     for(long long i=2;;i++)
     {
         x3=(3*x2+x1)%temp;
         if(x3==1&&x2==0)
         {
             printf("%I64d\n",i-1);
             break;
         }
         x1=x2;
         x2=x3;
     }求出第2层队222222224 取模。同理第3层对183120取模。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
struct matrix
{
    long long ma[3][3];
};
long long mod[3];
matrix multi(matrix x,matrix y,long long m)
{
    matrix ans;
    memset(ans.ma,0,sizeof(ans.ma));
    for(int i=1; i<=2; i++)
    {
        for(int j=1; j<=2; j++)
        {
            if(x.ma[i][j])
            {
                for(int k=1; k<=2; k++)
                {
                    ans.ma[i][k]=(ans.ma[i][k]+(x.ma[i][j]*y.ma[j][k])%m)%m;
                }
            }
        }
    }
    return ans;
}
int main()
{
    long long n;
    while(~scanf("%I64d",&n))
    {
        mod[0]=183120;
        mod[1]=222222224;
        mod[2]=1000000007;
        for(int l=0; l<3; l++)
        {
            if(n==0)
                continue;
            n=n-1;
            matrix a;
            a.ma[1][1]=1;
            a.ma[1][2]=a.ma[2][1]=a.ma[2][2]=0;
            matrix b;
            b.ma[1][1]=3;
            b.ma[1][2]=1;
            b.ma[2][1]=1;
            b.ma[2][2]=0;
            matrix ans;
            for(int i=1; i<=2; i++)
            {
                for(int j=1; j<=2; j++)
                {
                    if(i==j)
                        ans.ma[i][j]=1;
                    else
                        ans.ma[i][j]=0;
                }
            }
            while(n)
            {
                if(n&1)
                    ans=multi(ans,b,mod[l]);
                b=multi(b,b,mod[l]);
                n=n>>1;
            }
            n=ans.ma[1][1];
        }
        printf("%I64d\n",n);
    }
    return 0;
} 
                    
                 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号