zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    [noip2010]关押罪犯 并查集
    双栈排序 noip2008
    欧拉函数
    中国剩余定理(孙子定理)
    求组合数
    线性素数筛
    洛谷 P2661 信息传递
    图的最短路
    Mzc和男家丁的游戏
    最佳旅游线路
  • 原文地址:https://www.cnblogs.com/wally/p/2939110.html
Copyright © 2011-2022 走看看