zoukankan      html  css  js  c++  java
  • 【全国互虐】Fibonacci矩阵

    orz啊又被屠了 人生如此艰难

    题意:

    给定一个k维的n^k的超立方体 超立方体的元素Ai1,i2,...,ik 的值为f(i1+i2+...+ik-k+1) f为斐波那契数列

    求该超立方体的所有元素和

    1<=n,k<=10^9

    题解:

    其实看到数据范围 就大概猜到是矩阵乘法了

    但是我考试的时候想了半天还是不知道矩阵乘法怎么搞 - -

    其实矩阵乘法比我想象中的厉害多了

    这里有个性质 做完一维后 可以把这维压缩成一个点 用这维的和代替

    并且压缩后下一维还是满足斐波那契的性质所以可以用同一个矩阵继续乘
    那么把开始的[f[1],f[2],sum[1]] 改为[sum[n],sum[n]-f[1]+f[n+1],sum[n]] 继续快速幂即可

    但是这样做的时间复杂度是O(klogn)的

    其实上面的将[f[1],f[2],sum[1]] 改为[sum[n],sum[n]-f[1]+f[n+1],sum[n]]也是能用矩阵表示出来的orz

    具体自己yy下 这样就能求出从这维转到下一维的矩阵是什么样的 这个矩阵的k次方就能求出答案

    时间复杂度O(log(nk))

    代码

     1 #include <cstdio>
     2 #include <cstring>
     3 typedef long long ll;
     4 struct info{
     5     ll n,m;
     6     ll a[3][3];
     7 }save,jz,one,st;
     8 const ll mo=1000000007;
     9 ll t,n,m;
    10 inline info operator*(info a,info b){
    11     info res;
    12     res.n=a.n,res.m=b.m;
    13     for (ll i=0;i<res.n;i++)
    14     for (ll j=0;j<res.m;j++){
    15         res.a[i][j]=0;
    16         for (ll k=0;k<a.m;k++) res.a[i][j]=(res.a[i][j]+a.a[i][k]*b.a[k][j]%mo)%mo;
    17     }
    18     return res;
    19 }
    20 void makeinfo(){
    21     memset(st.a,0,sizeof(st.a));
    22     memset(one.a,0,sizeof(one.a));
    23     memset(save.a,0,sizeof(save.a));
    24     st.n=1,st.m=3;
    25     st.a[0][0]=1,st.a[0][1]=1,st.a[0][2]=1;
    26     one.n=one.m=save.n=save.m=3;
    27     one.a[0][0]=one.a[1][1]=one.a[2][2]=1;
    28     save.a[0][1]=save.a[1][2]=save.a[1][0]=save.a[1][1]=save.a[2][2]=1;
    29 }
    30 info mi(info a,ll b){
    31     info res=one;
    32     for (;b;b>>=1){
    33         if (b&1) res=res*a;
    34         a=a*a;
    35     }
    36     return res;
    37 }
    38 int main(){
    39     freopen("fibonacci.in","r",stdin);
    40     freopen("fibonacci.out","w",stdout);
    41     scanf("%I64d",&t);
    42     makeinfo();
    43     for (;t;t--){
    44         scanf("%I64d%I64d",&n,&m);
    45         jz=mi(save,n-1);
    46         jz.a[0][1]=jz.a[0][1]+jz.a[0][2]-1;
    47         jz.a[1][1]=jz.a[1][1]+jz.a[1][2];
    48         jz.a[2][1]=jz.a[2][1]+jz.a[2][2];
    49         jz.a[0][0]=jz.a[0][2];
    50         jz.a[1][0]=jz.a[1][2];
    51         jz.a[2][0]=jz.a[2][2];
    52         jz=mi(jz,m);
    53         jz=st*jz;
    54         printf("%I64d
    ",jz.a[0][0]);
    55     }
    56     fclose(stdin);
    57     fclose(stdout);
    58 }
    View Code
  • 相关阅读:
    yum安装nginx没有某一模块,该如何添加第三方模块?
    二进制部署K8S集群(二十四)k8s技术点整理
    opencv在python和c#中的对照应用-文字区域识别
    小区配置地图中心坐标
    Exception: No supported Visual Studio can be found. Supported versions are: 16.0 (2019), 15.0 (2017)
    文件包含
    kali linux 安装lanmp遇到的问题
    嵌入式实操----基于RT1170 首板硬件之SDRAM调试(十二)
    嵌入式实操----基于RT1170 DCD数据开发入门记录(十一)
    嵌入式实操----基于RT1170解决串口不支持float类型打印问题(十)
  • 原文地址:https://www.cnblogs.com/g-word/p/3757347.html
Copyright © 2011-2022 走看看