HDU-4686-Arc of Dream (矩阵快速幂)

版权声明:欢迎评论与转载,转载时请注明出处! https://blog.csdn.net/wjl_zyl_1314/article/details/84927934

原题链接:
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;
}

欢迎评论!

猜你喜欢

转载自blog.csdn.net/wjl_zyl_1314/article/details/84927934