HDU 4686 Arc of Dream (2013多校联合9 1001)

http://acm.hdu.edu.cn/showproblem.php?pid=4686


Arc of Dream

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


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.


思路:很明显且基础的矩阵乘法题,我们构造这样一个矩阵(5*5)


那么 下面这个1*5的矩阵


与上面所构造的矩阵相乘后的结果即为


那么我们要求AoD(n)用常规的矩阵加速乘法即可解决,复杂度为O(5*5*5*log(n))

下面是代码 :

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#define mod 1000000007
#define LL long long
using namespace std;
LL c[70][6][6];
LL ans[6][6];
int m=5;
void init(LL a[6][6],LL b[6][6], LL c[6][6])
{
    int i,j,k;
    LL tmp[6][6];
    memset(tmp,0,sizeof(tmp));
    for(i=1;i<=m;i++)
    {
        for(j=1;j<=m;j++)
        {
            for(k=1;k<=m;k++)
            {
                tmp[i][j]+=b[i][k]*c[k][j];
                tmp[i][j]%=mod;
            }
        }
    }
    for(i=1;i<=m;i++)
    {
        for(j=1;j<=m;j++)
        a[i][j]=tmp[i][j];
    }
}
void build(int num)
{
    if(num==1)
    return;
    build(num-1);
    init(c[num],c[num-1],c[num-1]);
}
LL tt[6];
void solve(LL n)
{
    if(n==0)
    {
       printf("0\n");
       return;
    }
    memset(ans,0,sizeof(ans));
    int t[70],num=0;
    while(n)
    {
        t[++num]=n%2;
        n/=2;
    }
    build(num);
    int i,j;
    for(i=1;i<=m;i++)
    {
        for(j=1;j<=m;j++)
        ans[i][j]=c[num][i][j];
    }
    for(i=1;i<num;i++)
    {
        if(t[i])
        {
            init(ans,ans,c[i]);
        }
    }
    LL sum=0;
    for(i=1;i<=m;i++)
    {
        sum=(sum+ans[i][1]*tt[i])%mod;
    }
    printf("%I64d\n",sum);
}
int main()
{
    freopen("dd.txt","r",stdin);
    LL a0,b0,ax,ay,bx,by,n;
    while(scanf("%I64d",&n)!=EOF)
    {
        scanf("%I64d%I64d%I64d",&a0,&ax,&ay);
        scanf("%I64d%I64d%I64d",&b0,&bx,&by);
        tt[1]=0,tt[2]=a0,tt[3]=b0,tt[4]=a0*b0%mod,tt[5]=1;
        memset(c,0,sizeof(c));
        c[1][1][1]=c[1][4][1]=c[1][5][5]=1;
        c[1][2][2]=ax;
        c[1][5][2]=ay;
        c[1][3][3]=bx;
        c[1][5][3]=by;
        c[1][2][4]=ax*by%mod;c[1][3][4]=bx*ay%mod;c[1][4][4]=ax*bx%mod,c[1][5][4]=ay*by%mod;
        solve(n);
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值