Calculation

13 篇文章 1 订阅

题目描述

定义下列函数:
题目描述

其中:
题目描述

给出了A0、AX、AY、B0、BX、BY。计算S(N)

输入

多组输入,每组输入包括三行。
第一行一个正整数N(1<=N<=1018)
第二行和第三行各包含三个非负整数:

A0 AX AY
B0 BX BY

其中A0,AX,AY,B0,BX,BY均不大于2x109

输出

输出S(N),对1000000007取模

样例输入

1
1 2 3
4 5 6

样例输出

130

#include <iostream>
#include<string.h>

using namespace std;

#define M 1000000007
#define LL long long

struct Matrix
{
    LL a[6][6];
}origin,res,tmp,A,ans;

int n = 5;
Matrix mul(Matrix x,Matrix y)
{
    int i,j,k;
    memset(tmp.a,0,sizeof(tmp.a));
    for(i=1;i<=n;i++)
        for(j=1;j<=n;j++)
            for(k=1;k<=n;k++)
            {
                tmp.a[i][j]+=(x.a[i][k]*y.a[k][j])%M;
                tmp.a[i][j]%=M;
            }
    return tmp;
}

void quickpow(LL k)
{
    int i;
    memset(res.a,0,sizeof(res.a));
    for(i=1;i<=n;i++)
        res.a[i][i]=1;
    while(k)
    {
        if(k&1)
            res=mul(res,A);
        A=mul(A,A);
        k>>=1;
    }
}

int main()
{
    LL a0, ax, ay, b0, bx, by, N;
    LL f1,a1,b1,s0;
    while(cin >> N) {
        cin >> a0 >> ax >> ay;
        cin >> b0 >> bx >> by;
        a1=(a0*ax+ay)%M;
        b1=(b0*bx+by)%M;
        f1=(a1*b1)%M;
        s0=0;
        memset(origin.a,0,sizeof(origin.a));
        origin.a[1][1]=f1;
        origin.a[1][2]=a1;
        origin.a[1][3]=b1;
        origin.a[1][4]=1;
        origin.a[1][5]=s0;
        memset(A.a,0,sizeof(A.a));
        A.a[1][1]=(ax*bx)%M;
        A.a[1][5]=1;
        A.a[2][1]=(ax*by)%M;
        A.a[2][2]=ax%M;
        A.a[3][1]=(ay*bx)%M;
        A.a[3][3]=bx%M;
        A.a[4][1]=(ay*by)%M;
        A.a[4][2]=ay%M;
        A.a[4][3]=by%M;
        A.a[4][4]=1;
        A.a[5][5]=1;

        quickpow(N);
        ans=mul(origin,res);
        printf("%lld\n",ans.a[1][5]);
    }
    return 0;
}
    这道题单纯从逻辑上讲是很简单的,貌似一下就写出来了,但是仔细一看,这里的N是大的可怕,正常做法绝对会超时(自己试一下就知道好慢的说)。网上看到大神是将递归归纳成矩阵快速幂,然后这样就不用一个一个执行了。(发现这个方法真的很好用,很多地方都用得到!)

下面是具体思路参考的博客,很清楚。
http://www.cnblogs.com/frog112111/archive/2013/08/21/3273660.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值