• 【全国互虐】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
  • 相关阅读:
    axios——post请求时把对象obj数据转为formdata格式
    【工作问题记录】
    如何在Vue项目中使用Element组件
    Manjaro 安装教程
    真 ● 禁秘技 ● 奥义 ● 终端美化
    Docker下MySQL的安装
    Linux Nvidia显卡驱动安装
    Linux下Matlab的安装
    解决SQLPLUS无法使用上下箭头
    @Transactional+@Autowired出现的lateinit property xx has not been initialized错误
  • 原文地址:https://www.cnblogs.com/g-word/p/3757347.html
Copyright © 2020-2023  润新知