HDU 6050 - Funny Function | 2017 Multi-University Training Contest 2

/*
HDU 6050 - Funny Function  [ 公式推导,矩阵快速幂 ]
题意:
	F(1,1) = F(1, 2) = 1
	F(1,i) = F(1, i-1) + 2 * F(1, i-2) , i >= 3
	F(i, j) = ∑ F(i-1, j) , k∈[j, j+N-1]
	给定 N, M  < 2^63, 求 F(M,1)
分析:
	∵	F(2,1) = F(1,1) + F(1,2) + ... + F(1,N)
		F(2,2) = F(2,1) + F(1,N+1) - F(1,1)
	
	∴	2*F(2,1) + F(2,2) = 3*F(2,1) + F(1,N+1) - F(1,1)
						  = ( F(1,1) + 2*F(1,1)+F(1,2) + 2*F(1,2)+F(1,3) + ... + 2*F(1,N-1)+F(1,N) + 2*F(1,N) ) + F(1,N+1) - F(1,1)
						  = F(1,1) + ( F(1,3) + F(1,4) + ... + F(1,N+1) ) + 2*F(1,N) + F(1,N+1)
						  = F(1,3) + F(1,4) + ... + F(1,N+2)
						  = F(2,3)
	
	将结论推至一般情况:F(i,j) = F(i,j-1) + 2*F(i,j-2) .......(1)
	
	∵	F(2,1) = F(1,1) + F(1,2) + ... + F(1,N)
		F(2,1) + F(1,1) = 2*F(1,1) + F(1,2) + ... + F(1,N)
						= 2*F(1,3) + F(1,4) + ... + F(1,N)
	
	∴	当N为偶数时 F(2,1) = F(1,N+1) - F(1,1)
		当N为奇数时	F(2,1) = 2*F(1,N) - F(1,1)

	当N为偶数时:
		F(2,1) = F(1,N+1) - F(1,1)
		F(2,2) = F(1,N+2) - F(1,2)
		写为矩阵形式:
		( F(2,2) , F(2,1) ) = ( F(1,N+2) - F(1,1) , F(1,N+1) - F(1,1) )
							= ( F(1,N+2) , F(1,N+1) ) - ( F(1,2) , F(1,1) )
							= ( A^N - I ) * ( F(1,2) , F(1,1) )
	∴	根据结论(1)
		( F(M,2) , F(M,1) ) = ( A^N - I )^M * ( F(1,2) , F(1,1) )

	当N为奇数时:
		F(2,1) = 2*F(1,N) - F(1,1)
		F(2,2) = 2*F(1,N+1) - F(1,2)
		写为矩阵形式:
		( F(2,2) , F(2,1) ) = ( 2*F(1,N+1) - F(1,1) , 2*F(1,N) - F(1,1) )
							= 2*( F(1,N+2) , F(1,N+1) ) - ( F(1,2) , F(1,1) )
							= ( 2 * A^(N-1) - I ) * ( F(1,2) , F(1,1) )
	∴	根据结论(1)
		( F(M,2) , F(M,1) ) = ( 2 * A^(N-1) - I )^M * ( F(1,2) , F(1,1) )	

编码时长: INF(-2)
*/
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const LL MOD = 1e9+7;
const int sz = 2;
struct Matrix {
    LL a[sz][sz];
    Matrix() {
        memset(a, 0, sizeof(a));
    }
    Matrix operator * (const int & t) const {
        Matrix C;
        for (int i = 0; i < sz; i++)
            for (int j = 0; j < sz; j++)
                C.a[i][j] = a[i][j] * t % MOD;
        return C;
    }
    Matrix operator * (const Matrix &B) const {
        Matrix C;
        for (int i = 0; i < sz; i++)
            for (int k = 0; k < sz; k++)
                for (int j = 0; j < sz; j++)
                    C.a[i][j] = (C.a[i][j] + a[i][k]*B.a[k][j] % MOD) % MOD;
        return C;
    }
    Matrix operator ^ (const LL &t) const {
        Matrix A = (*this), res;
        for (int i = 0; i < sz; i++) res.a[i][i] = 1;
        LL p = t;
        while (p) {
            if (p&1) res = res*A;
            A = A*A;
            p >>= 1;
        }
        return res;
    }
}A, B, C;
LL n, m, ans;
void init()
{
    A.a[0][0] = 1; A.a[0][1] = 2;
    A.a[1][0] = 1; A.a[1][1] = 0;
}
void solve()
{
    if (m == 1 || n == 1) ans = 1;
    else if (n&1)
    {
        B = A^(n-1);
        B = B*2;
        for (int i = 0; i < 2; i++) B.a[i][i] = (B.a[i][i] + MOD-1) % MOD;
        C = B^(m-1);
        ans = (C.a[1][0] + C.a[1][1]) % MOD;
    }
    else
    {
        B = A^n;
        for (int i = 0; i < 2; i++) B.a[i][i] = (B.a[i][i] + MOD-1) % MOD;
        C = B^(m-1);
        ans = (C.a[1][0] + C.a[1][1]) % MOD;
    }
}
int main()
{
    int t; scanf("%d", &t);
    while (t--)
    {
        scanf("%lld%lld", &n, &m);
        init();
        solve();
        printf("%lld\n", ans);
    }
}

 

posted @ 2017-07-28 13:43  nicetomeetu  阅读(239)  评论(0编辑  收藏  举报