多校联合第九场1001HDU4686 Arc of Dream

3 篇文章 0 订阅
1 篇文章 0 订阅

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

题意描述的很直观,给你公式:a0 = A0,ai = ai-1*AX+AY,b0 = B0,bi = bi-1*BX+BY,再给一个n要求从a0*b0到a(n-1)*b(n-1)的累加和。n很大,所以不用考虑暴力了。

从给的公式我们可以得到几点:

1).ai=AX *a(i-1)+AY;                                                                  

2).bi=BX*b(i-1)+BY;

3).  ai*bi=(AX*BX)*a(i-1)*b(i-1)+(AX*BY)*a(i-1)+(AY*BX)*b(i-1)+(AY*BY)*1;

设Si为累加到ai*bi的和,则

4).Si=S(i-1)+ai*bi;

所以可以构造出这样的矩形:

ai*bi           AX*BX   AX*BY   AY*BX  AY*BY  0                  a(i-1)*b(i-1)

ai                0           AX         0          AY      0                     a(i-1)

bi         =    0           0           BX       BY       0         *          b(i-1)

1                0           0            0        1            0                    1

si                AX*BX   AX*BY   AY*BX  AY*BY  1                   s(i-1)

最后再用矩阵的快速幂乘法就可以得到结果了,注意是(n-1)次,还有就是这题需要特判n==0的时候,不然会一直WA到底的。。。。=.=

贴一下代码:

#include <cstdio>
#include <cstring>
typedef long long LL;
#define mod 1000000007

LL matrix[5][5],tmp[5][5],mirror[5][5];
LL A0,B0,AX,AY,BX,BY;
void init()//初始化左乘矩阵
{
	memset(matrix,0,sizeof(matrix));
	matrix[0][0]=AX*BX%mod,matrix[0][1]=AX*BY%mod,matrix[0][2]=AY*BX%mod,matrix[0][3]=AY*BY%mod,matrix[0][4]=0;
	matrix[1][1]=AX%mod,matrix[1][3]=AY%mod;
	matrix[2][2]=BX%mod,matrix[2][3]=BY%mod;
	matrix[3][3]=1;
	matrix[4][0]=AX*BX%mod,matrix[4][1]=AX*BY%mod,matrix[4][2]=AY*BX%mod,matrix[4][3]=AY*BY%mod,matrix[4][4]=1;
	memcpy(mirror,matrix,sizeof(matrix));
}

void matrix_mult(LL a[][5],LL b[][5] )
{
	for(int i=0;i<5;i++)
		for(int j=0;j<5;j++)
		{
			tmp[i][j]=0;
			for(int k=0;k<5;k++)
			{
				tmp[i][j]+=(a[i][k]*b[k][j]%mod);
				tmp[i][j]%=mod;
			}
		}
	memcpy(a,tmp,sizeof(tmp));
}
void cal_matrix(LL n)
{
	memset(mirror,0,sizeof(mirror));
	for(int i=0;i<5;i++) mirror[i][i]=1;
	while(n)
	{
		if(n&1)//二进制当前位为1
			matrix_mult(mirror,matrix);
		matrix_mult(matrix,matrix);
		n>>=1;
	}	 
}
void cal_ans()
{
	LL ans=0;
	ans=(ans+mirror[4][0]*A0%mod*B0%mod)%mod;
	ans=(ans+mirror[4][1]*A0%mod)%mod;
	ans=(ans+mirror[4][2]*B0%mod)%mod;
	ans=(ans+mirror[4][3])%mod;
	ans=(ans+mirror[4][4]*A0%mod*B0%mod)%mod;
	printf("%I64d\n",ans );
}
int main()
{
	LL n;

	while(scanf("%I64d",&n)==1)//注意在hdu上不能用lld
	{
		scanf("%I64d%I64d%I64d",&A0,&AX,&AY);
		scanf("%I64d%I64d%I64d",&B0,&BX,&BY);
		if(n==0)
		{
			printf("0\n");
			continue;//不特判0会wa
		}
		init();
		cal_matrix(n-1);
		cal_ans();
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值