hdu 1588 又是矩阵
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1588
比hdu 1757难了好多,看了好多别人的博客才明白。。。哎。。。
View Code
1 /* 2 *题意:g(i)=k*i+b,sum(f(g(i)) for 0<=i<n 3 *根据Fibonacci矩阵的求法,f(i)=mat^i 令mat={1,1,1,0}(二阶矩阵) 4 *f(g(i))=mat^g(i)=mat^(ki+b) 5 *sum(f(g(i))=mat^b+mat^(k+b)+...+mat^(ki+b) for 0<=i<n 6 *提取mat^b得:sum(f(g(i))=mat^b+mat^b[mat^(k)+mat^2k...+mat^(ki)] 7 *问题转化为求 mat^(k)+mat^2k...+mat^(ki) 8 *对等比矩阵进行二分求和,做法如下: 9 *求得matk=mat^k 10 *原式=matk+matk^2+...+matk^i 11 *如果 i 为偶数:原式=(matk+matk^2+...+matk^i/2)+matk^(i/2)(matk+matk^2+...+matk^i/2) 12 *如果(i)为奇数:那我们干脆先计算前面的i-1个偶数 13 * 用前面所诉的方法 tmp1=matk+matk^2+...+matk^i/2 tmp2=tmp1*matk^i/2 14 * 前偶数个的和tmp=tmp1+tmp2 15 * 最后的结果=tmp+matk^i 16 */ 17 18 19 #include<iostream> 20 using namespace std; 21 22 int k,b,n,m; 23 struct Matrix { 24 __int64 map[2][2]; 25 }; 26 Matrix matrix,matk,matb,smat; 27 28 //矩阵乘法 29 Matrix Mul(Matrix &a,Matrix &b){ 30 Matrix c; 31 for(int i=0;i<2;i++){ 32 for(int j=0;j<2;j++){ 33 c.map[i][j]=0; 34 for(int k=0;k<2;k++){ 35 c.map[i][j]+=a.map[i][k]*b.map[k][j]; 36 c.map[i][j]%=m; 37 } 38 } 39 } 40 return c; 41 } 42 43 //快速幂 44 Matrix Pow(int k,Matrix &temp){ 45 if(k==1)return temp; 46 else if(k&1){ 47 return Mul(temp,Pow(k-1,temp)); 48 }else { 49 Matrix tmp=Pow(k>>1,temp); 50 return Mul(tmp,tmp); 51 } 52 } 53 54 //矩阵加法 55 Matrix Sum(Matrix &a,Matrix &b){ 56 Matrix c; 57 for(int i=0;i<2;i++){ 58 for(int j=0;j<2;j++){ 59 c.map[i][j]=a.map[i][j]+b.map[i][j]; 60 c.map[i][j]%=m; 61 } 62 } 63 return c; 64 } 65 66 //等比数列二分求和 67 Matrix Binary_Sum(int k){ 68 if(k==1)return matk; 69 else if(k&1){ 70 //奇数时前k-1项与matk^k相加 71 return Sum(Binary_Sum(k-1),Pow(k,matk)); 72 }else { 73 Matrix tmp1=Binary_Sum(k>>1);//先算前k/2项 74 Matrix tmp2=Mul(Pow(k>>1,matk),tmp1); 75 return Sum(tmp1,tmp2); 76 } 77 } 78 79 int main(){ 80 matrix.map[0][0]=1,matrix.map[0][1]=1; 81 matrix.map[1][0]=1,matrix.map[1][1]=0; 82 while(scanf("%d%d%d%d",&k,&b,&n,&m)!=EOF){ 83 matk=Pow(k,matrix);//求matrix^k; 84 smat=Binary_Sum(n-1);//求matk的等比数列的前n-1项和 85 if(b){ 86 matb=Pow(b,matrix); 87 smat=Mul(matb,smat);//sum=sum*matb; 88 smat=Sum(matb,smat);//sum+=matb; 89 } 90 printf("%I64d\n",smat.map[1][0]); 91 } 92 return 0; 93 }
附上一链接:http://www.cppblog.com/notonlysuccess/archive/2009/03/03/75405.aspx