题目链接: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;
}