HDU 4686 Arc of Dream

题目大意:

        有多个测例(以EOF结束),要求输出求和值a0b0 + a1b1...+ an-1bn-1,其中a0, b0已知,并且ai = ai-1AX + AY,bi = bi-1BX + BY,其中AX、AY、BX、BY已知,其中n ≤ 10^18,a0、b0、AX、AY、BX、BY ≤ 2×10^9。

题目链接

注释代码:

/*                                                
 * Problem ID : HDU 4686 Arc of Dream  
 * Author     : Lirx.t.Una                                                
 * Language   : C                               
 * Run Time   : 250 ms                                                
 * Run Memory : 204 KB                                                
*/

#include <memory.h>
#include <stdio.h>

#define    MOD(x)        ( (x) % 1000000007 )

typedef    __int64        llg;

//思路:
//a[i+1]       =   AY(1) +   AX(a[i]) +    0(b[i]) +    0(a[i]b[i]) + 0(s[i])
//b[i+1]       =   BY(1) +    0(a[i]) +   BX(b[i]) +    0(a[i]b[i]) + 0(s[i])
//a[i+1]b[i+1] = AYBY(1) + AXBY(a[i]) + AYBX(b[i]) + AXBX(a[i]b[i]) + 0(s[i])
//s[i+1]       = AYBY(1) + AXBY(a[i]) + AYBX(b[i]) + AXBX(a[i]b[i]) + 1(s[i])
//其中s[n-1]即为问题的答案
//由上述方程组可得矩阵:
//M = 1   a0  b0 a0b0 s1=a0b0
//    0   0   0   0   0
//    0   0   0   0   0
//    0   0   0   0   0
//    0   0   0   0   0
//
//C = 1  AY  BY  AYBY  AYBY
//    0  AX  0   AXBY  AXBY
//    0  0   BX  AYBX  AYBX
//    0  0   0   AXBX  AXBX
//    0  0   0   0     1
//最终结果就是M×C^(n-1)的元素[1][5]

llg        m[6][6];//main,主矩阵矩阵
llg        c[6][6];//coefficient,系数矩阵
llg        t[6][6];//tmp,临时矩阵

void
mul( llg (*ma)[6], llg (*mb)[6] ) {//矩阵相乘,结果保存在ma中

    int        i, j, k;

    memset(t, 0, sizeof(t));

    for ( i = 1; i < 6; i++ )
        for ( k = 1; k < 6; k++ )
            if ( ma[i][k] )
                for ( j = 1; j < 6; j++ ) {
        
                    t[i][j] += MOD( ma[i][k] * mb[k][j] );
                    t[i][j]  = MOD( t[i][j] );
                }

    memcpy(ma, t, sizeof(t));
}

void
fstp(llg n) {//矩阵快速幂,结果保存在m中

    while (n) {
    
        if ( n & 1 ) mul( m, c );
        mul( c, c );
        n >>= 1;
    }
}

int
main() {

    llg        n;
    llg        a0, b0;
    llg        ax, ay;
    llg        bx, by;

    while ( ~scanf("%I64d", &n) ) {
    

        scanf("%I64d%I64d%I64d%I64d%I64d%I64d",
              &a0, &ax, &ay, &b0, &bx, &by);

        if ( !n ) {//特殊情况判断
        
            puts("0");
            continue;
        }

	if ( 1 == n ) {//特判,加速
		
		printf("%d\n", MOD( a0 * b0 ));
		continue;
	}

	//初始化
        memset(m, 0, sizeof(m));
        memset(c, 0, sizeof(c));

        m[1][1] = 1;
        m[1][2] = MOD(a0);
        m[1][3] = MOD(b0);
        m[1][4] = MOD( a0 * b0 );
        m[1][5] = m[1][4];

        c[1][1] = 1;
        c[1][2] = MOD(ay);
        c[1][3] = MOD(by);
        c[1][4] = MOD( ay * by );
        c[1][5] = c[1][4];

        c[2][2] = MOD(ax);
        c[2][4] = MOD( ax * by );
        c[2][5] = c[2][4];

        c[3][3] = MOD(bx);
        c[3][4] = MOD( ay * bx );
        c[3][5] = c[3][4];

        c[4][4] = MOD( ax * bx );
        c[4][5] = c[4][4];

        c[5][5] = 1;

        fstp(n - 1);//快速幂
        printf("%I64d\n", m[1][5]);
    }

    return 0;
}
无注释代码:

#include <memory.h>
#include <stdio.h>

#define    MOD(x)        ( (x) % 1000000007 )

typedef    __int64        llg;

llg        m[6][6];
llg        c[6][6];
llg        t[6][6];

void
mul( llg (*ma)[6], llg (*mb)[6] ) {

    int        i, j, k;

    memset(t, 0, sizeof(t));

    for ( i = 1; i < 6; i++ )
        for ( k = 1; k < 6; k++ )
            if ( ma[i][k] )
                for ( j = 1; j < 6; j++ ) {
        
                    t[i][j] += MOD( ma[i][k] * mb[k][j] );
                    t[i][j]  = MOD( t[i][j] );
                }

    memcpy(ma, t, sizeof(t));
}

void
fstp(llg n) {

    while (n) {
    
        if ( n & 1 ) mul( m, c );
        mul( c, c );
        n >>= 1;
    }
}

int
main() {

    llg        n;
    llg        a0, b0;
    llg        ax, ay;
    llg        bx, by;

    while ( ~scanf("%I64d", &n) ) {
    

        scanf("%I64d%I64d%I64d%I64d%I64d%I64d",
              &a0, &ax, &ay, &b0, &bx, &by);

        if ( !n ) {
        
            puts("0");
            continue;
        }

		if ( 1 == n ) {
		
			printf("%d\n", MOD( a0 * b0 ));
			continue;
		}

        memset(m, 0, sizeof(m));
        memset(c, 0, sizeof(c));

        m[1][1] = 1;
        m[1][2] = MOD(a0);
        m[1][3] = MOD(b0);
        m[1][4] = MOD( a0 * b0 );
        m[1][5] = m[1][4];

        c[1][1] = 1;
        c[1][2] = MOD(ay);
        c[1][3] = MOD(by);
        c[1][4] = MOD( ay * by );
        c[1][5] = c[1][4];

        c[2][2] = MOD(ax);
        c[2][4] = MOD( ax * by );
        c[2][5] = c[2][4];

        c[3][3] = MOD(bx);
        c[3][4] = MOD( ay * bx );
        c[3][5] = c[3][4];

        c[4][4] = MOD( ax * bx );
        c[4][5] = c[4][4];

        c[5][5] = 1;

        fstp(n - 1);
        printf("%I64d\n", m[1][5]);
    }

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值