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

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值