1. 程式人生 > >HDU 5950 - Recursive sequence - [矩陣快速冪加速遞推][2016ACM/ICPC亞洲區瀋陽站 Problem C]

HDU 5950 - Recursive sequence - [矩陣快速冪加速遞推][2016ACM/ICPC亞洲區瀋陽站 Problem C]

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=5950

Farmer John likes to play mathematics games with his N cows. Recently, they are attracted by recursive sequences. In each turn, the cows would stand in a line, while John writes two positive numbers a and b on a blackboard. And then, the cows would say their identity number one by one. The first cow says the first number a and the second says the second number b. After that, the i-th cow says the sum of twice the (i-2)-th number, the (i-1)-th number, and $i^4$. Now, you need to write a program to calculate the number of the N-th cow in order to check if John’s cows can make it right.

Input
The first line of input contains an integer t, the number of test cases. t test cases follow. 
Each case contains only one line with three numbers N, a and b where $N,a,b < 2^31$ as described above.

Output
For each test case, output the number of the N-th cow. This number might be very large, so you need to output it modulo $2147493647$.

Sample Input
2
3 1 2
4 1 10

Sample Output
85
369

Hint
In the first case, the third number is $85 = 2 \times 1 + 2 + 3^4$.
In the second case, the third number is $93 = 2 \times 1 + 1 \times 10 + 3^4$ and the fourth number is $369 = 2 \times 10 + 93 + 4^4$.

 

題意:

給出 $a,b,n$,已知 $a_1 = a, a_2 = b$,且對於 $i>2$ 的 $a_i = 2a_{i-2} + a_{i-1} + i^4$,求 $a_n$。

 

題解:

看一眼 $n$ 最大在 $2e9$,顯然不是暴力的遞推。考慮矩陣快速冪加速遞推。

不妨設一個矩陣

那麼就有

我們只要求出一個矩陣 $A$,使其滿足 $F(n+1) = F(n) \times A$,就能進行矩陣快速冪加速遞推。

根據二項式定理很容易得到

因此不難就求得滿足 $F(n+1) = F(n) \times A$ 矩陣 $A$ 如下:

此時,對於任意的 $F(n)$,都可以由 $F(n) = F(2) \times A^{n-2}$ 求得,$A^{n-2}$ 用矩陣快速冪可以 $O(\log n)$ 求出。

 

AC程式碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=2147493647;

const int DIM=7;
struct Matrix
{
    ll mat[DIM][DIM];
    Matrix operator*(Matrix const &oth)const
    {
        Matrix res;
        memset(res.mat,0,sizeof(res.mat));
        for(int i=0;i<DIM;i++)
            for(int j=0;j<DIM;j++)
                for(int k=0;k<DIM;k++)
                    res.mat[i][j]+=(mat[i][k]*oth.mat[k][j])%mod,
                    res.mat[i][j]%=mod;
        return res;
    }
}A,F2,Fn;
Matrix fpow(Matrix base,ll n)
{
    Matrix res;
    memset(res.mat,0,sizeof(res.mat));
    for(int i=0;i<DIM;i++) res.mat[i][i]=1;
    while(n)
    {
        if(n&1) res=res*base;
        base=base*base;
        n>>=1;
    }
    return res;
}

void initA()
{
    A.mat[0][0]=0, A.mat[0][1]=2, A.mat[0][2]=0, A.mat[0][3]=0, A.mat[0][4]=0, A.mat[0][5]=0, A.mat[0][6]=0;
    A.mat[1][0]=1, A.mat[1][1]=1, A.mat[1][2]=0, A.mat[1][3]=0, A.mat[1][4]=0, A.mat[1][5]=0, A.mat[1][6]=0;
    A.mat[2][0]=0, A.mat[2][1]=1, A.mat[2][2]=1, A.mat[2][3]=0, A.mat[2][4]=0, A.mat[2][5]=0, A.mat[2][6]=0;
    A.mat[3][0]=0, A.mat[3][1]=0, A.mat[3][2]=4, A.mat[3][3]=1, A.mat[3][4]=0, A.mat[3][5]=0, A.mat[3][6]=0;
    A.mat[4][0]=0, A.mat[4][1]=0, A.mat[4][2]=6, A.mat[4][3]=3, A.mat[4][4]=1, A.mat[4][5]=0, A.mat[4][6]=0;
    A.mat[5][0]=0, A.mat[5][1]=0, A.mat[5][2]=4, A.mat[5][3]=3, A.mat[5][4]=2, A.mat[5][5]=1, A.mat[5][6]=0;
    A.mat[6][0]=0, A.mat[6][1]=0, A.mat[6][2]=1, A.mat[6][3]=1, A.mat[6][4]=1, A.mat[6][5]=1, A.mat[6][6]=1;
}

ll n,a,b;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);

    initA();
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>a>>b;
        if(n==1) {
            cout<<a<<'\n';
            continue;
        }
        if(n==2) {
            cout<<b<<'\n';
            continue;
        }

        memset(F2.mat,0,sizeof(F2.mat));
        memset(Fn.mat,0,sizeof(Fn.mat));

        F2.mat[0][0]=a, F2.mat[0][1]=b,
        F2.mat[0][2]=3*3*3*3, F2.mat[0][3]=3*3*3, F2.mat[0][4]=3*3, F2.mat[0][5]=3, F2.mat[0][6]=1;

        Fn=F2*fpow(A,n-2);
        cout<<Fn.mat[0][1]<<'\n';
    }
}