【HDOJ 4686】 Arc of Dream (矩阵快速幂)
两个公式
a(i) = a(i-1)*Ax+Ay
b(i) = b(i-1)*Bx+By
0~(n-1) 的a(i)*b(i)
初始矩阵为 求幂矩阵为
a0 Ax 0 0 0 Ay
b0 0 Bx 0 0 By
a0*b0 Ax*By Ay*Bx Ax*Bx 0 Ay*By
0 0 0 1 1 0
1 0 0 0 0 0
(艾玛 这么生敲矩阵太累人了。。。。还好行列不多。。。
这样经过一次矩阵乘法之后 会变成。。。
a1
b1
a1*b1
a0*b0
1
两次
a2
b2
a2*b2
a0*b0+a1*b1
1
......自己写写看 乘的过程就不写了。。忒累了
然后写个矩阵乘法套个快速幂就WA了………………精度要求 一开始是开成long long了。。。不过初始矩阵传成了int。。。该打。。。。
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #define ll long long #define mod 1000000007 using namespace std; typedef struct Matrix Matrix; struct Matrix { ll mx[5][5]; void Init(ll ax,ll ay,ll bx,ll by)//初始矩阵 { memset(mx,0,sizeof(mx)); mx[0][0] = ax; mx[0][4] = ay; mx[1][1] = bx; mx[1][4] = by; mx[2][0] = ax*by%mod; mx[2][1] = ay*bx%mod; mx[2][2] = ax*bx%mod; mx[2][4] = ay*by%mod; mx[3][2] = mx[3][3] = mx[4][4] = 1; } void Emp()//单位矩阵 { memset(mx,0,sizeof(mx)); for(int i = 0; i < 5; ++i) mx[i][i] = 1; } Matrix operator * (const Matrix a)const//矩阵乘法 { Matrix x; memset(x.mx,0,sizeof(x.mx)); for(int i = 0; i < 5; ++i) for(int j = 0; j < 5; ++j) for(int k = 0; k < 5; ++k) x.mx[i][j] = (x.mx[i][j]+mx[i][k]*a.mx[k][j]%mod)%mod; return x; } }; Matrix pow(Matrix a,ll b)//快速幂 { Matrix ans; ans.Emp(); while(b) { if(b&1) ans = ans*a; a = a*a; b >>= 1; } return ans; } int main() { ll n,a,b,ax,ay,bx,by; while(~scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&a,&ax,&ay,&b,&bx,&by))//没改 杭电的题 注意改成I64d { a%=mod; b%=mod; ax%=mod; ay%=mod; bx%=mod; by%=mod; Matrix mx; mx.Init(ax,ay,bx,by); mx = pow(mx,n); printf("%lld\n",(((a*mx.mx[3][0]%mod+b*mx.mx[3][1]%mod)%mod+a%mod*b%mod*mx.mx[3][2]%mod)%mod+mx.mx[3][4])%mod); } return 0; }