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); } }
我自倾杯,君且随意