1. 程式人生 > >HDU-4686-Arc of Dream (矩陣快速冪)

HDU-4686-Arc of Dream (矩陣快速冪)

原題連結:
An Arc of Dream is a curve defined by following function:
在這裡插入圖片描述

where
a 0 = A0
a i = a i-1AX+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.
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
題意:
根據公式可以計算出來ai和bi,然後求和sum(aibi)。
題解:
這道題目,如果直接計算必然會超時,但是隻要捋清楚裡面遞推的關係,就可以用矩陣來表示關係,之後利用矩陣快速冪即可計算出結果。
遞推關係:
ai

bi=axbxa[i-1]b[i-1]+axbya[i-1]+aybxb[i-1]+ayby
然而我們要求的是sum【n】,所以要將sum【n】=sum【n-1】+ai*bi加進去,最終得到矩陣(詳細矩陣見程式碼初始化)
附上AC程式碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define LL long long
const int N=5;
const int mod=1000000007;
struct Matrix//定義矩陣結構體
{
    LL a[N][N];
    Matrix ()//無參建構函式
    {
        memset(a,0,sizeof(a));
    }
    Matrix operator *( Matrix b)//定義矩陣乘法符號
    {
        Matrix tmp;
        for(int i=0;i<N;++i)
            for(int j=0;j<N;++j)
                for(int k=0;k<N;++k)
        tmp.a[i][j]=(tmp.a[i][j]+a[i][k]*b.a[k][j])%mod;
        return tmp;
    }
}res,ans;
LL n,a0,ax,ay,b0,bx,by;
Matrix quickpow(Matrix a,LL b)//矩陣快速冪(原理類似於整數快速冪)
{
    Matrix res;
    for(int i=0;i<N;++i)
        res.a[i][i]=1;
    while(b!=0)
    {
        if(b&1)
            res=res*a;
        a=a*a;
        b>>=1;
    }
    return res;
}
int main()
{
    while(scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&a0,&ax,&ay,&b0,&bx,&by)!=EOF)
    {
        if(n==0)
        {
            printf("0\n");
            continue;
        }
        memset(res.a,0,sizeof(res.a));//以下7行均為初始化
        memset(ans.a,0,sizeof(ans.a));
        ans.a[0][0]=ans.a[0][1]=(a0%mod*b0%mod)%mod;
        ans.a[0][2]=b0%mod,ans.a[0][3]=a0%mod,ans.a[0][4]=1;
        res.a[0][0]=1;
        res.a[1][0]=res.a[1][1]=(ax%mod*bx%mod)%mod;
        res.a[2][0]=res.a[2][1]=(ay%mod*bx%mod)%mod,res.a[2][2]=bx%mod;
        res.a[3][0]=res.a[3][1]=(ax%mod*by%mod)%mod,res.a[3][3]=ax%mod;
        res.a[4][0]=res.a[4][1]=(ay%mod*by%mod)%mod,res.a[4][2]=by%mod,res.a[4][3]=ay%mod,res.a[4][4]=1;
        res=quickpow(res,n-1);//快速冪計算
        ans=ans*res;
        printf("%lld\n",(ans.a[0][0]+mod)%mod);
    }
    return 0;
}

歡迎評論!