HDOJ Arc of Dream 4686【矩阵快速幂】



Arc of Dream

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 3126    Accepted Submission(s): 982


Problem Description
An Arc of Dream is a curve defined by following function:

where
a 0 = A0
a i = a i-1*AX+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
 

Author
Zejun Wu (watashi)
 

Source
 

Recommend
zhuyuanchen520   |   We have carefully selected several similar problems for you:   5390  5389  5388  5387  5386 
 


题意:看公式就可以了。。。。ai*bi的数列前n项(0—n-1)求和。

解题思路:10^18次方。。果断利用矩阵快速幂。。关键是找出相乘的矩阵。

1

0

0

1

0

0

Ax

0

0

Ay

   0   

0

Bx

0

By

0

 Ax*By 

 Bx*Ay 

 Ax*Bx 

 Ay*By 

0

0

0

0

1








就是利用上述矩阵去乘以

Si-1

ai-1

bi-1

ai-1*bi-1

1








它们相乘的结果就是

Si

ai

bi

 ai*b

1












所以直接对第一个矩阵进行N阶快速幂。乘以第二个矩阵,得到最后一个矩阵,输出第一个元素即可。


AC代码:

#include <stdio.h>
#include <math.h>
#include <vector>
#include <queue>
#include <string>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;
const int MAXN = 5;
const LL Modn = 1000000007;
LL res[MAXN][MAXN];
LL a[MAXN][MAXN];
LL A0,Ax,Ay,B0,Bx,By;

void Matmul(LL X[MAXN][MAXN],LL Y[MAXN][MAXN])
{
    LL t[MAXN][MAXN]={0};
    for(int i=0;i<MAXN;i++){
        for(int k=0;k<MAXN;k++)
            if(X[i][k])
            for(int j=0;j<MAXN;j++)
            t[i][j]=(t[i][j]+X[i][k]*Y[k][j]%Modn)%Modn;
    }
    for(int i=0;i<MAXN;i++)
        for(int j=0;j<MAXN;j++)
        X[i][j]=t[i][j];
}

void Matrix(LL X[MAXN][MAXN],LL n)
{
    for(int i=0;i<MAXN;i++)
        for(int j=0;j<MAXN;j++)
        res[i][j]=(i==j);
    while(n){
        if(n&1) Matmul(res,X);
        Matmul(X,X);
        n>>=1;
    }
}

void init()
{
    memset(a,0,sizeof(a));
    a[0][0]=a[0][3]=1;
    a[1][1]=Ax%Modn;a[1][4]=Ay%Modn;
    a[2][2]=Bx%Modn;a[2][4]=By%Modn;
    a[3][1]=Ax*By%Modn;a[3][2]=Bx*Ay%Modn;
    a[3][3]=Ax*Bx%Modn;a[3][4]=Ay*By%Modn;
    a[4][4]=1;
}

int main()
{
    LL N,S;
    while(scanf("%lld",&N)!=EOF){
        LL ans[5];
        scanf("%lld%lld%lld%lld%lld%lld",&A0,&Ax,&Ay,&B0,&Bx,&By);
        if(N==0){
            printf("0\n");
            continue;
        }
        ans[0]=0;ans[1]=A0;ans[2]=B0;ans[3]=A0*B0%Modn;ans[4]=1;
        init();
        Matrix(a,N);
        S=0;
        for(int i=0;i<MAXN;i++){
            S=(S+ans[i]*res[0][i]%Modn)%Modn;
        }
        printf("%lld\n",S);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值