Description
An Arc of Dream is a curve defined by following function:
where
a 0 = A0
a i = a i-1*AX+AY
b 0 = B0
b i = b i-1*BX+BY
What is the value of AoD(N) modulo 1,000,000,007?
where
a 0 = A0
a i = a i-1*AX+AY
b 0 = B0
b i = b i-1*BX+BY
What is the value of AoD(N) modulo 1,000,000,007?
Input
There are multiple test cases. Process to the End of File.
Each test case contains 7 nonnegative integers as follows:
N
A0 AX AY
B0 BX BY
N is no more than 10 18, and all the other integers are no more than 2×10 9.
Each test case contains 7 nonnegative integers as follows:
N
A0 AX AY
B0 BX BY
N is no more than 10 18, and all the other integers are no more than 2×10 9.
Output
For each test case, output AoD(N) modulo 1,000,000,007.
Sample Input
1 1 2 3 4 5 6 2 1 2 3 4 5 6 3 1 2 3 4 5 6
Sample Output
4 134 1902
矩阵快速幂的精华:跟求通项式一样,从底层向高层推
AoD(n) = AoD(n-1) + a(n)*b(n) = Aod(n-1) + AX*BX*a(n-1)*b(n-1) + AX*BY*a(n-1) + AY*BX*b(n-1) + AYBY
如此我们可以提取出一个矩阵B = [Aod(n-1) , a(n-1)*b(n-1) , a(n-1) , b(n-1) , 1].
那么接下来我们要构造矩阵就是让B变成我们想要的Aod(n)
1 | 0 | 0 | 0 | 0 |
AX*BX | AX*BX | 0 | 0 | 0 |
AX*BY | AX*BY | AX | 0 | 0 |
AY*BX | AY*BX | 0 | BX | 0 |
AY*BY | AY*BY | AY | BY | AY*BY |
找到了需要构造的矩阵A,Bn = A^(n-1) * B, Aod(n) = Bn[0][0]
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int mod = 1e9+ 7;
typedef long long LL;
typedef vector<LL>vec;
typedef vector<vec>mat;
mat mul(mat &A, mat &B) {//两个矩阵相乘
mat C(A.size(), vec(B[0].size()));
for(int i = 0; i < A.size(); i ++) {
for(int k = 0; k < B.size(); k ++) {
for(int j = 0; j < B[0].size(); j ++) {
C[i][j] = (C[i][j] + A[i][k] * B[k][j]) % mod;
}
}
}
return C;
}
mat pow(mat A, LL n) {//矩阵快速幂
mat B(A.size(), vec(A.size()));
for(int i = 0; i < A.size(); i ++) B[i][i] = 1;
while(n) {
if(n & 1) B = mul(B, A);
A = mul(A, A);
n >>= 1;
}
return B;
}
LL N ,A0, AX, AY, B0,BX, BY;
int main() {
while(~scanf("%I64d%I64d%I64d%I64d%I64d%I64d%I64d",&N ,&A0, &AX, &AY, &B0, &BX, &BY)) {
if(N == 0) {
printf("0\n");
continue;
}
mat A(5, vec(5)), B(1, vec(5));
A[0][0] = 1, A[0][1] = 0, A[0][2] = 0, A[0][3] = 0,A[0][4] = 0;
A[1][0] = (AX * BX) % mod, A[1][1] = (AX * BX) % mod, A[1][2] = 0, A[1][3] = 0, A[1][4] = 0;
A[2][0] = (AX * BY) % mod, A[2][1] = (AX * BY) % mod, A[2][2] = AX % mod, A[2][3] = 0, A[2][4] = 0;
A[3][0] = (AY * BX) % mod, A[3][1] = (AY * BX) % mod, A[3][2] = 0, A[3][3] = BX % mod, A[3][4] = 0;
A[4][0] = (AY * BY) % mod, A[4][1] = (AY * BY) % mod, A[4][2] = AY % mod, A[4][3] = BY % mod, A[4][4] = 1;
B[0][0] = (A0 * B0) % mod, B[0][1] = (A0 * B0) % mod, B[0][2] = A0 % mod, B[0][3] = B0 % mod, B[0][4] = 1;
A = pow(A, N - 1);
B = mul(B, A);
printf("%I64d\n", B[0][0]);
}
return 0;
}