zoukankan      html  css  js  c++  java
  • P1939 矩阵加速(数列)

           这个题若不看题目和范围,我首先想到用递推,不过   n≤2×10^9,若用递推,一定会超时。

    要用矩阵加速的话首先要找到一个矩阵(不唯一),用来相乘;

    〔a1,a2,a3〕是一个1×3的矩阵,我想把它转化为〔a2,a3,a4〕也是一个1×3的矩阵,所以要找的矩阵肯定是3×3的;

    可以假设这个3×3的矩阵为       所以 a2=a1×a+a2×b+a3×c 所以a=0;b=1;c=0;同理可得d=0;e=0;f=1;

    a4=a3+a1 所以 g=1;h=0;i=1;所以3×3的矩阵应为     可以看出若想得出an,则需要这个矩阵的(n-3)次方再乘

    〔a1,a2,a3〕因为a1,a2,a3都为1,所以可以不用乘,最后得出〔a n-2,a n-1,a n〕;用 r[4][4]来存储乘完后的3×3矩阵,

    则an就是 r[1][3]+r[2][3]+r[3][3];通过快速幂就能快速求出答案了。

    其实这个题套用 P 3390 矩阵快速幂的代码就可以,所以我就不再解释了,关于矩阵如何快速幂的问题在上一篇博客(☜点他)已说明。

    直接上完整代码:

     1 #include<iostream>
     2 using namespace std;
     3 struct hls{
     4     long long s[4][4];
     5 };
     6 hls t,r;
     7 long long k;
     8 const long long m=1000000007;
     9 hls operator * (const hls &a,const hls &b)
    10 {
    11     hls w;
    12     for(int i=1;i<=3;++i)
    13     {
    14         for(int j=1;j<=3;++j)
    15         {
    16             w.s[i][j]=0;
    17         }
    18     }
    19     for(int x=1;x<=3;++x)
    20     {
    21         for(int y=1;y<=3;++y)
    22         {
    23             for(int z=1;z<=3;++z)
    24             {
    25                 w.s[x][y]+=(a.s[x][z]%m)*(b.s[z][y]%m);
    26                 w.s[x][y]%=m;
    27             }
    28         }
    29     }
    30     return w;
    31 }
    32 int main()
    33 {
    34     int q;
    35     cin>>q;
    36     while(q--)
    37     {
    38         cin>>k;
    39         for(int i=1;i<=3;++i)
    40         {
    41             for(int j=1;j<=3;++j)
    42             {
    43                 t.s[i][j]=0;
    44                 if(i!=j) r.s[i][j]=0;
    45                 else r.s[i][j]=1;
    46             }
    47         }
    48         t.s[1][3]++; 
    49         t.s[2][1]++; 
    50         t.s[3][2]++; 
    51         t.s[3][3]++;
    52         k=k-3;
    53         while(k>0) 
    54         {
    55             if(k%2==1) r=r*t;
    56             t=t*t;
    57             k/=2;
    58         }
    59         cout<<(r.s[1][3]+r.s[2][3]+r.s[3][3])%m<<endl;
    60     }
    61     return 0;
    62 }
  • 相关阅读:
    2016-7-4工作总结
    2016-7第一周工作总结
    2016-6-30 工作总结
    2016-6-29 工作总结
    2016-6-28 工作总结
    基于软件开发对嵌入式开发的思考
    团队项目总结
    软件工程课程总结
    图描述之:流程图
    004-二叉树的遍历
  • 原文地址:https://www.cnblogs.com/zkw666/p/12457407.html
Copyright © 2011-2022 走看看