zoukankan      html  css  js  c++  java
  • 距阵的运用

    昨晚大四的一个学长给我们讲了,距阵的使用,很不错,这里总结一下。

    一般距阵,用在n很大,导致超时的问题上。它需要快速幂取模的辅助。

    例子

    求斐波那契数列   a1=1;    a2=1;     an=an-1+an-2;   求 an     (n>=1&&n<=108)    由于n很大结果对999999999取模;

    对于这题n很大你直接推,每次取%999999999,明显会超时,

    矩阵做法

    这样就可以化为 矩阵(a1 a2)*矩阵(An-1)= 矩阵(an,an+1);

    看代码

    #include<stdio.h>
    #include<string.h>
    #define mod 999999999

    __int64 a[5];
    __int64 b[3][3];

    __int64 quick_mod(__int64 n)
    {
    a[1]=1; a[2]=1;
    b[1][1]=0; b[1][2]=1;
    b[2][1]=1; b[2][2]=1;
    while(n)
    {
    if(n&1)
    {
    __int64 s1,s2;
    s1=(a[1]*b[1][1]%mod+a[2]*b[2][1]%mod)%mod;
    s2=(a[1]*b[2][1]%mod+a[2]*b[2][2]%mod)%mod;
    a[1]=s1;
    a[2]=s2;
    n--;
    }
    n=n/2;
    __int64 k1,k2,k3,k4;
    k1=(b[1][1]*b[1][1]%mod+b[1][2]*b[2][1]%mod)%mod;
    k2=(b[1][1]*b[2][1]%mod+b[1][2]*b[2][2]%mod)%mod;
    k3=(b[2][1]*b[1][1]%mod+b[2][2]*b[2][1]%mod)%mod;
    k4=(b[2][1]*b[1][2]%mod+b[2][2]*b[2][2]%mod)%mod;
    b[1][1]=k1; b[1][2]=k2; b[2][1]=k3; b[2][2]=k4;
    }
    return a[1];
    }

    int main(void)
    {
    __int64 n;
    while(scanf("%I64d",&n)==1)
    {
    printf("%I64d ",quick_mod(n-1));
    }
    return 0;
    }

    这样就运用快速幂取模大大减少了时间。

    如果矩阵大一点的话这样写

    #include<stdio.h>
    #include<string.h>
    #define mod 999999999

    __int64 a[5];
    __int64 b[3][3];

    __int64 quick_mod(__int64 n)
    {
    __int64 i,j,k;
    a[1]=1; a[2]=1;
    b[1][1]=0; b[1][2]=1;
    b[2][1]=1; b[2][2]=1;
    while(n)
    {
    if(n&1)
    {
    __int64 s[3];
    memset(s,0,sizeof(s));
    for(i=1;i<=2;i++)
    {
    for(j=1;j<=2;j++)
    {
    s[i]=(s[i]+a[j]*b[j][i])%mod;
    }
    }
    for(i=1;i<=2;i++)
    a[i]=s[i];
    n--;
    }
    n=n/2;
    __int64 kk[5][5];
    memset(kk,0,sizeof(kk));
    for(i=1;i<=2;i++)
    {
    for(j=1;j<=2;j++)
    {
    for(k=1;k<=2;k++)
    {
    kk[i][j]=(kk[i][j]+b[i][k]*b[k][j])%mod;
    }
    }
    }
    for(i=1;i<=2;i++)
    {
    for(j=1;j<=2;j++)
    {
    b[i][j]=kk[i][j];
    }
    }
    }
    return a[1];
    }

    int main(void)
    {
    __int64 n;
    while(scanf("%I64d",&n)==1)
    {
    printf("%I64d ",quick_mod(n-1));
    }
    return 0;
    }

  • 相关阅读:
    【转】iOS:AvPlayer设置播放速度不生效的解决办法
    【转】 Android xml中 @和?区别,style和attr小结
    【转】Android 旋转动画,停止和持续旋转
    【转】Android SDK,ADT,API 版本的对应关系
    【转】说说Android中的style和theme
    【转】 Android中selector的使用
    【转】[置顶] 在Android中显示GIF动画
    mysql if case条件更新
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
  • 原文地址:https://www.cnblogs.com/liudehao/p/4148258.html
Copyright © 2011-2022 走看看