HDU 3306 Another kind of Fibonacci

HDU_3306

    由于N很大,所以需要在找出递推关系的基础上用二分矩阵来优化计算过程。

    根据S(n)=S(n-1)+A(n)^2,A(n)^2=X^2*A(n-1)^2+Y^2*A(n-2)^2+2*X*Y*A(n-1)*A(n-2),A(n)*A(n-1)=Y*A(n-1)*A(n-2)+X*A(n-1)^2,可以构造如下的矩阵,然后用二分矩阵的方法求解即可。

    

#include<stdio.h>
#include<string.h>
#define D 10007
#define MAXD 4
int N, X, Y;
struct Matrix
{
    int a[MAXD][MAXD];
    Matrix()
    {
        memset(a, 0, sizeof(a));
    }
};
Matrix multiply(Matrix &x, Matrix &y)
{
    int i, j, k, ans;
    Matrix z;
    for(k = 0; k < 4; k ++)
        for(i = 0; i < 4; i ++)
            if(x.a[i][k])
            {
                for(j = 0; j < 4; j ++)
                    if(y.a[k][j])
                        z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j]) % D;
            }
    return z;
}
void powmod(Matrix &unit, Matrix &mat, int n)
{
    while(n)
    {
        if(n & 1)
            unit = multiply(mat, unit);
        n >>= 1;
        mat = multiply(mat, mat);
    }
}
void solve()
{
    int i;
    Matrix unit, mat;
    for(i = 0; i < 4; i ++)
        unit.a[i][0] = 1;
    mat.a[0][0] = mat.a[0][1] = 1;
    mat.a[1][1] = (X * X) % D, mat.a[1][2] = (Y * Y) % D, mat.a[1][3] = (2 * X * Y) % D;
    mat.a[2][1] = 1;
    mat.a[3][1] = X, mat.a[3][3] = Y;
    powmod(unit, mat, N);
    printf("%d\n", unit.a[0][0]);
}
int main()
{
    while(scanf("%d%d%d", &N, &X, &Y) == 3)
    {
        X %= D, Y %= D;
        solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/staginner/p/2471507.html