HDU 6050 Funny Function (矩阵快速幂)
Description
函数\(F_{x,y}\)满足:
\(F_{1,1}=F_{1,2}=1\)
\(F_{1,j}=F_{1,j-1}+2F_{1,j-2}\ (j\geqslant 3)\)
\(F_{i,j}=\sum_{k=j}^{j+N-1}{F_{i-1,k}}\ (i \geqslant 2, j \geqslant 1)\)
给出整数\(N\)和\(m\),计算\(F_{m,1}\ mod\ 1e9+7\)。
Input
第一行一个整数\(T\)表示用例组数,接下来\(T\)行,每行两个整数\(N\)和\(m\)。\(1 \leqslant N,m \leqslant 2^{63}\)。
Output
对于每组用例输出\(F_{m,1}\ mod\ 1e9+7\)。
Sample Input
2
2 2
3 3
Sample Output
2
33
Solution
\(F_{1,j}=F_{i,j-1}+2F_{i,j-2}\ (i \geqslant 1, j \geqslant 3)\\\)
\(\sum_{k=1}^j{F_{i,k}}=F_{i,j+1}-F_{i,1}\ (j为偶数)\\ \sum_{k=1}^j{F_{i,k}}=F_{i,j+1}+F_{i,1}-F_{i,2}\ (j为奇数)\)
\((F_{i,1},F_{i,2})=(F_{i-1,n+1}-F_{i-1,1},F_{i-1,n+2}-F_{i-1,2})\)
\(=(F_{i-1,n+1},F_{i-1,n+2})-(F_{i-1,1},F_{i-1,2})\)
\(=(F_{i-1,1},F_{i-1,2})A^n-(F_{i-1,1},F_{i-1,2})\)
\(=(F_{i-1,1},F_{i-1,2})(A^n-B_0)\ (n为偶数)\)
\((F_{m,1},F_{m,2})=(F_{1,1},F_{1,2})(A^n-B_0)^{m-1}\ (n为偶数)\)
\((F_{m,1},F_{m,2})=(F_{1,1},F_{1,2})(A^n-B_1)^{m-1}\ (n为奇数)\)
\(其中A,B_0,B_1均为二阶矩阵\)
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const int N = 5;
const int nn = 2;
struct Matrix
{
ll a[5][5], n;
Matrix(ll x = 0, ll b = 0, ll c = 0, ll d = 0)
{
n = 2;
a[1][1] = x; a[1][2] = b;
a[2][1] = c; a[2][2] = d;
}
ll* operator[](int i)
{
return a[i];
}
};
Matrix operator-(Matrix A, Matrix B)
{
ll n = A.n;
Matrix C;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
C[i][j] = ((A[i][j] - B[i][j]) % mod + mod) % mod;
return C;
}
Matrix operator*(Matrix A, Matrix B)
{
int n = A.n;
Matrix C;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
C[i][j] = (C[i][j] + A[i][k] * B[k][j] % mod) % mod;
return C;
}
Matrix power(Matrix A, ll n, ll mod)
{
Matrix C(1, 0, 0, 1);
while (n)
{
if (n & 1) C = C * A;
A = A * A;
n >>= 1;
}
return C;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
ll n, m;
scanf("%lld%lld", &n, &m);
Matrix A(0, 2, 1, 1);
Matrix B = n & 1 ? Matrix(-1, 2, 1, 0) : Matrix(1, 0, 0, 1);
A = power(A, n, mod) - B;
A = power(A, m - 1, mod);
ll ans = (A[1][1] + A[2][1]) % mod;
printf("%lld\n", ans);
}
return 0;
}