# Arc of Dream

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 126    Accepted Submission(s): 44

Problem Description
An Arc of Dream is a curve defined by following function:

where
a0 = A0
ai = ai-1*AX+AY
b0 = B0
bi = bi-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 1018, and all the other integers are no more than 2×109.

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

Author
Zejun Wu (watashi)

Source

Recommend
zhuyuanchen520

1、 如果Ax 和 Bx 为1时，  an, bn都是等差数列。
2、其中一个为1时，就是等差 * 等比.
3、否则是等比 * 等比。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;

//

const int V = 100000 + 50;
const int MaxN = 500 + 5;
const int mod = 1000000007;
const int inf = 1987654321;
__int64 n, A0, Ax, Ay, B0, Bx, By;
__int64 Quick_Pow(__int64 a, __int64 b) {
__int64 res = 1;
while(b) {
if(b & 1)
res = (res * a) % mod;
b /= 2;
a = (a * a) % mod;
}
return res % mod;
}
__int64 f() {
__int64 a = ((A0 * (Ax - 1) + mod) % mod + Ay % mod) % mod;
__int64 b = ((B0 * (Bx - 1) + mod) % mod + By % mod) % mod;
__int64 c = Quick_Pow(Ax, n) * Quick_Pow(Bx, n) % mod - 1;
c = (c + mod) % mod;
__int64 d = (Ax * Bx - 1 + mod) % mod * (Ax - 1 + mod) % mod * (Bx - 1 + mod) % mod;
__int64 e = Quick_Pow(d, mod - 2);
return (a * b % mod * c % mod * e % mod);
}
__int64 g() {
__int64 a = ((B0 * (Bx - 1) + mod) % mod + By % mod) % mod;
__int64 b = 1 -  Quick_Pow(Bx, n);
b = (b + mod) % mod;
__int64 c = ((Ax - 1) * (Bx - 1) + mod) % mod * ((Bx - 1 + mod) % mod) % mod;
__int64 d = Quick_Pow(c, mod - 2);
return (Ay % mod * a % mod * b % mod * d % mod);
}
__int64 h() {
__int64 a = ((A0 * (Ax - 1) + mod) % mod + Ay % mod) % mod;
__int64 b = 1 - Quick_Pow(Ax, n);
b = (b + mod) % mod;
__int64 c = ((Bx - 1) * (Ax - 1) + mod) % mod * ((Ax - 1 + mod) % mod) % mod;
__int64 d = Quick_Pow(c, mod - 2);
return (By % mod * a % mod * b % mod * d % mod);
}
int main() {
int i, j, k;
while(~scanf("%I64d", &n)) {
scanf("%I64d%I64d%I64d", &A0, &Ax, &Ay);
scanf("%I64d%I64d%I64d", &B0, &Bx, &By);
__int64 a, b, c, d, e;
if(Ax == 1 && Bx == 1) {//等差*等差
a = (n % mod) * A0 % mod * B0 % mod;
b = (n % mod) * ((n - 1) % mod) % mod * Quick_Pow(2, mod - 2) % mod * ((Ay * B0 % mod + A0 * By % mod) % mod) % mod;
c = (n - 1) % mod * (n % mod) % mod * ((2 * n - 1) % mod) % mod * Quick_Pow(6, mod - 2) % mod * Ay % mod * By % mod;
printf("%I64d\n", ((a + b) % mod + c) % mod);
}
else if(Ax == 1 || Bx == 1) {//等比*等差
if(Bx == 1) {
__int64 temp = B0;
B0 = A0;
A0 = temp;
temp = Bx;
Bx = Ax;
Ax = temp;
temp = By;
By = Ay;
Ay = temp;
}
a = ((B0 * (Bx - 1) + mod) % mod + By % mod) % mod * A0 % mod * Quick_Pow(((Bx - 1) * (Bx - 1) + mod) % mod, mod - 2) % mod;
b = ((B0 * (Bx - 1) + mod) % mod + By % mod) % mod * Ay % mod * Bx % mod * ((Quick_Pow(Bx, n - 1) - 1 + mod) % mod) % mod;
c = ((Bx - 1) * (Bx - 1) + mod) % mod * ((Bx - 1 + mod) % mod) % mod;
b = b * Quick_Pow(c, mod - 2) % mod;
d = (A0 % mod + (n - 1 + mod) % mod * Ay % mod) % mod * (((B0 * (Bx - 1) + mod) % mod + By % mod) % mod) % mod * Quick_Pow(Bx, n) % mod;
c = ((Bx - 1) * (Bx - 1) + mod) % mod;
d = d * Quick_Pow(c, mod - 2) % mod;
e = (n % mod * A0 % mod + n % mod * ((n - 1 + mod) % mod) % mod * Ay % mod * Quick_Pow(2, mod - 2) % mod) % mod * By % mod * Quick_Pow((Bx - 1 + mod) % mod, mod - 2) % mod;
// printf("%I64d %I64d %I64d %I64d\n", a, b, d, e);
printf("%I64d\n", (((d - a + mod) % mod - b + mod) % mod - e + mod) % mod);
}
else {//等比*等比
a = f();
b = g();
c = h();
d = (Ay * By % mod) * (n % mod) % mod * Quick_Pow(((Ax - 1) * (Bx - 1) + mod) % mod, mod - 2) % mod;
printf("%I64d\n", ((((a + b) % mod + c) % mod) + d) % mod);
}
}
}

ai = ai-1 * Ax + Ay;
bi = bi-1 * Bx + By;
ai * bi = ai-1 * bi-1 * (Ax * Bx) + ai-1 * (Ax * By) + bi-1 * (Bx * Ay) + AyBy;
Si = Si - 1 + ai * bi = Si - 1  + ai-1 * bi-1 * (Ax * Bx) + ai-1 * (Ax * By) + bi-1 * (Bx * Ay) + AyBy;

[1， A0,  B0,  A0 * B0,  A0 * B0]  即 [1, a0, b0, a0 * b0, S0]
[0 …… 0]

N次递推得

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int V = 100000 + 50;
const int mod = 1000000000 + 7;
const int MaxN = 5;
struct Matrix{
__int64 mat[MaxN][MaxN];
};
Matrix init, Pow;
__int64 n, A0, Ax, Ay, B0, Bx, By;
Matrix multi(Matrix a, Matrix b) {
Matrix ans;
for(int i = 0; i < MaxN; ++i)
for(int j = 0; j < MaxN; ++j) {
__int64 sum = 0;
for(int k = 0; k < MaxN; ++k)
sum = (sum + a.mat[i][k] * b.mat[k][j] % mod) % mod;
ans.mat[i][j] = sum;
}
return ans;
}
Matrix MatrixQuickPow(Matrix a, __int64 b) {
Matrix ans = init;
while(b) {
if(b & 1)
ans = multi(ans, a);
b /= 2;
a = multi(a, a);
}
return ans;
}
int main() {
while(~scanf("%I64d", &n)) {
scanf("%I64d%I64d%I64d%I64d%I64d%I64d", &A0, &Ax, &Ay, &B0, &Bx, &By);
if(!n) {
printf("0\n");
continue;
}
init.mat[0][0] = 1;
init.mat[0][1] = A0;
init.mat[0][2] = B0;
init.mat[0][3] = init.mat[0][4] = A0 * B0 % mod;
Pow.mat[0][0] = Pow.mat[4][4] = 1;
Pow.mat[0][1] = Ay;
Pow.mat[0][2] = By;
Pow.mat[0][3] = Pow.mat[0][4] = Ay * By % mod;
Pow.mat[1][1] = Ax;
Pow.mat[2][2] = Bx;
Pow.mat[1][3] = Pow.mat[1][4] = Ax * By % mod;
Pow.mat[2][3] = Pow.mat[2][4] = Ay * Bx % mod;
Pow.mat[3][3] = Pow.mat[3][4] = Ax * Bx % mod;
/*
for(int i = 0; i < MaxN; ++i) {
for(int j = 0; j < MaxN; ++j)
printf("%I64d ", Pow.mat[i][j]);
printf("\n");
}*/
Matrix ans = MatrixQuickPow(Pow, n - 1);
printf("%I64d\n", ans.mat[0][4]);
}
}