标签:
题目连接:传送门
题意:
给定ai,bi的推倒公式,求sigma(ai*bi) ( 0<= i < n)
分析:
A0 = A0
Ai = Ai-1*Ax+Ay
B0 = B0
Bi = Bi-1*Bx+By
设Fi表示Ai*Bi
Fi = Ai * Bi
===> Fi = (Ai-1*Ax + Ay)*(Bi-1*Bx + By)
===> Fi = Ax*Bx*(Ai-1*Bi-1) + Ax*By*Ai-1 + Bx*Ay*Bi-1
===> Fi = Fi-1 + Ax*By*Ai-1 + Bx*Ay*Bi-1 + Ay*By
| F[i] | | 1 , Ax*By , Bx*Ay , Ay*By | | F[i-1] |
| Ai | = | 0 , Ax , 0 , Ay | * | Ai-1 |
| Bi | | 0 , 0 , Bx , By | | Bi-1 |
| 1 | | 0 , 0 , 0 , 1 | | 1 |
设sum[i] = sigma(ak*bk) ( 0<= k < i)
sum[i] = sum[i-1] + F[i]
sum[i] = sum[i-1] + Fi-1 + Ax*By*Ai-1 + Bx*Ay*Bi-1 + Ay*By
因此可以得到一个包含sum的状态转移矩阵
| sum[i] | | 1 , 1 , Ax*By , Bx*Ay , Ay*By | | sum[i-1] |
| F[i] | | 0 , 1 , Ax*By , Bx*Ay , Ay*By | | F[i-1] |
| Ai | = | 0 , 0 , Ax , 0 , Ay | * | Ai-1 |
| Bi | | 0 , 0 , 0 , Bx , By | | Bi-1 |
| 1 | | 0 , 0 , 0 , 0 , 1 | | 1 |
这题需要注意的是n==0 输出0,注意使用long long,防止中间运算溢出
具体代码如下:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int N = 5; typedef __int64 LL; const LL mod = 1e9+7; struct matrix{ LL a[N][N]; matrix(){ memset(a,0,sizeof(a)); } }I; void init(){ for(int i=0;i<N;i++) I.a[i][i]=1; } matrix multi(matrix A, matrix B){ matrix C ; for(int i=0;i<N;i++){ for(int j=0;j<N;j++){ C.a[i][j]=0; for(int k=0;k<N;k++){ C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j]%mod)%mod; } } } return C; } matrix quick(matrix A, LL n){ matrix ans = I; while(n){ if(n&1) ans = multi(A,ans); n>>=1; A=multi(A,A); } return ans; } int main() { init(); LL n,a0,b0,x1,y1,x2,y2; while(~scanf("%I64d",&n)){ scanf("%I64d%I64d%I64d",&a0,&x1,&y1); scanf("%I64d%I64d%I64d",&b0,&x2,&y2); if(n==0){ puts("0"); continue; } x2=x2%mod;b0=b0%mod;y2=y2%mod; x1=x1%mod;a0=a0%mod;y1=y1%mod; matrix A=matrix(); A.a[0][0]=1LL; A.a[0][1]=x1*x2%mod; A.a[0][2]=x1*y2%mod; A.a[0][3]=x2*y1%mod; A.a[0][4]=y1*y2%mod; A.a[1][1]=x1*x2%mod; A.a[1][2]=x1*y2%mod; A.a[1][3]=x2*y1%mod; A.a[1][4]=y1*y2%mod; A.a[2][2]=x1; A.a[2][4]=y1; A.a[3][3]=x2; A.a[3][4]=y2; A.a[4][4]=1LL; LL sum = 0; matrix ans = quick(A,n-1); sum =(sum + a0*b0%mod*ans.a[0][0]%mod)%mod; sum =(sum + a0*b0%mod*ans.a[0][1]%mod)%mod; sum =(sum + a0*ans.a[0][2]%mod)%mod; sum =(sum + b0*ans.a[0][3]%mod)%mod; sum =(sum + ans.a[0][4]%mod)%mod; printf("%I64d\n",sum); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/bigbigship/article/details/47403323