Hdu 4686 Arc of Dream 矩阵快速幂

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4686

题目大意:已知a[0],ax,ay,  其中a[i] = ax * a[i-1] + ay;

         已知b[0],bx,by   其中b[i] = bx * b[i-1] + by;

         求 a[i]*b[i] (0 =< i <= (n-1)) 的和;

代码如下:

/* 由a[n-1]*b[n-1] = a[n-2]*b[n-2]*ax*bx + a[n-2]*ax*by + b[n-2]*ay*bx + ay * by; 
*  设前n项和为sum[n],则:
*     sum[n]=sum[n-1]+a[n-1]*b[n-1];        
*           =sum[n-1]+a[n-2]*b[n-2]*ax*bx + a[n-2]*ax*by + b[n-2]*ay*bx + ay * by;
                                                                                   {   1     0     0   0   0 } 
*                                                                                  { ax*bx  ax*bx  0   0   0 } 
*{sum[n],a[n-1]*b[n-1],a[n-1],b[n-1],1} = {sum[n-1],a[n-2]*b[n-2],a[n-1],b[n-2],1}*{ ax*by  ax*by  ax  0   0 } 
*                                                                                  { ay*bx  ay*bx  0   bx  0 } 
*                                                                                  { ay*by  ay*by  ay  by  1 } 
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define mod 1000000007
LL n;
struct mat
{
    LL ma[5][5];
};
mat cal(mat a,mat b)
{
    mat c;
    memset(c.ma,0,sizeof(c.ma));
    for(int i=0;i<5;i++)
    for(int k=0;k<5;k++)
    for(int j=0;j<5;j++)
    c.ma[i][j]=(c.ma[i][j]+a.ma[i][k]*b.ma[k][j])%mod;
    return c;
}
mat pow(mat a,LL k)
{
    mat e;
    memset(e.ma,0,sizeof(e.ma));
    for(int i=0;i<5;i++)
        e.ma[i][i]=1;
    while(k>0)
    {
        if(k&1) e=cal(e,a);
        a=cal(a,a);
        k>>=1;
    }
    return e;
}

int main()
{
    LL a0,ax,ay,b0,bx,by;
    while(~scanf("%I64d",&n))
    {
        scanf("%I64d%I64d%I64d%I64d%I64d%I64d",&a0,&ax,&ay,&b0,&bx,&by);
        if(n==0) {printf("0\n");continue;}
        if(n==1) {printf("%I64d\n",a0*b0%mod);continue;}
        mat x;
        memset(x.ma,0,sizeof(x.ma));
        x.ma[0][0]=1;x.ma[0][1]=ax*bx%mod;x.ma[0][2]=ax*by%mod;x.ma[0][3]=bx*ay%mod;x.ma[0][4]=ay*by%mod;
        x.ma[1][0]=0;x.ma[1][1]=ax*bx%mod;x.ma[1][2]=ax*by%mod;x.ma[1][3]=bx*ay%mod;x.ma[1][4]=ay*by%mod;
        x.ma[2][0]=0;x.ma[2][1]=0;x.ma[2][2]=ax%mod;x.ma[2][3]=0;x.ma[2][4]=ay%mod;
        x.ma[3][0]=0;x.ma[3][1]=0;x.ma[3][2]=0;x.ma[3][3]=bx%mod;x.ma[3][4]=by%mod;
        x.ma[4][0]=0;x.ma[4][1]=0;x.ma[4][2]=0;x.ma[4][3]=0;x.ma[4][4]=1;
        x=pow(x,n-1);
        LL k=a0*b0%mod;
        LL ans=(x.ma[0][0]*k+k*x.ma[0][1]+a0*x.ma[0][2]+b0*x.ma[0][3]+x.ma[0][4])%mod;
        printf("%I64d\n",ans);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值