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

 

 

 

 

你可能感兴趣的:(HDU)