题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4686
Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)

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

Problem solving report:

Description: 让你求Aod(n)的值,其中每个元素的计算公式已给出。
Problem solving: 因为n比较大,即使是O(n)也是一样会超时,所以我们采用矩阵快速幂的方式来解题。

a[i]=a[i-1]*AX+AY;
b[i]=b[i-1]*BX+BY;
a[i]*b[i]=a[i-1]*b[i-1]*AX*BX+a[i-1]*AX*BY+b[i-1]*BX*AY+AY*BY;
S[i]=S[i-1]+a[i]*b[i]=S[i-1]+a[i-1]*b[i-1]*AX*BX+a[i-1]*AX*BY+b[i-1]*BX*AY+AY*BY;
根据上式可知

根据S[i],一定需要S[i-1],a[i-1]*b[i-1],a[i-1],b[i-1],常数。矩阵大小为5.

构造初始矩阵ANS0

转换矩阵a.使得


根据上面4个公式得:


现在要求 AoD(n)=ans(n-1), 求出ans*a^(n-1)的第一行第一个元素就行了。

另外注意要判断一下n等于0的情况,这个判断条件很重要,没有就会TLE。

Accepted Code:

/* 
 * @Author: lzyws739307453 
 * @Language: C++ 
 */
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 1000000007;
struct mat {
    ll m[6][6];
    mat() {
       memset(m, 0, sizeof(m));
    }
}a, ans;
mat mul(mat a, mat b) {
    mat p;
    for (int i = 0; i < 5; i++)
        for (int j = 0; j < 5; j++)
            for (int k = 0; k < 5; k++)
                p.m[i][j] = (p.m[i][j] + (a.m[i][k] * b.m[k][j]) % MOD) % MOD;
    return p;
}
mat power(mat a, ll k) {
    mat p;
    for (int i = 0; i < 5; i++)
        p.m[i][i] = 1;
    while (k) {
        if (k & 1)
            p = mul(p, a);
        a = mul(a, a);
        k >>= 1;
    }
    return p;
}
int main() {
    ll n, a_, b_, ax, ay, bx, by;
    while (~scanf("%lld", &n)) {
        scanf("%lld%lld%lld", &a_, &ax, &ay);
        scanf("%lld%lld%lld", &b_, &bx, &by);
        if (!n) {
            printf("0\n");
            continue;
        }
        a.m[0][0] = 1;
        a.m[1][0] = ax * bx % MOD, a.m[1][1] = ax * bx % MOD;
        a.m[2][0] = ax * by % MOD, a.m[2][1] = ax * by % MOD, a.m[2][2] = ax % MOD;
        a.m[3][0] = ay * bx % MOD, a.m[3][1] = ay * bx % MOD, a.m[3][2] = 0, a.m[3][3] = bx % MOD;
        a.m[4][0] = ay * by % MOD, a.m[4][1] = ay * by % MOD, a.m[4][2] = ay % MOD, a.m[4][3] = by % MOD, a.m[4][4] = 1;
        ans.m[0][0] = a_ * b_ % MOD, ans.m[0][1] = a_ * b_ % MOD, ans.m[0][2] = a_ % MOD, ans.m[0][3] = b_ % MOD, ans.m[0][4] = 1;
        ans = mul(ans, power(a, n - 1));
        printf("%lld\n", ans.m[0][0]);
    }
    return 0;
}