zoukankan      html  css  js  c++  java
  • Xn数列(矩阵乘法+快速幂+慢速乘法)

    Xn数列

    题目描述:
    给你6个数,m, a, c, x0, n, g
    Xn+1 = ( aXn + c ) mod m,求Xn
    m, a, c, x0, n, g<=10^18
    输入描述:
    一行六个数 m, a, c, x0, n, g
    输出描述:
    输出一个数 Xn mod g
    样例输入:
    11 8 7 1 5 3
    样例输出:
    2
    数据范围及提示:
    int64按位相乘可以不要用高精度。
    思路:
    暴力循环求解?NO~NO~NO~
    如此大的数据,想到矩阵乘法,利用矩阵加速。
    这道题的难度在于如何推出矩阵。
    首先根据矩阵性质以及运算规则容易看出这是2*2的矩阵
    让X0位于a[1][1]的位置。那么运算之后X1肯定也要位于a[1][1]的位置
    因为X1=a*X0+c,所以a[1][2]的位置是c,a[2][1]和a[2][2]对于答案没有影响,所以设为0就可以了,至此,初始矩阵设置完毕。
    那么初始矩阵乘以哪一个矩阵才能得到答案呢?重新定义一个矩阵b,容易看出,当b[1][1]=a,b[1][2]=0,b[2][1]=1,b[2][2]=1时,矩阵a*矩阵b才能得到我们想要的答案。
    这里写图片描述
    可以看出:
    a*b可以得出X1,同样的X1*b得出X2,,即:X2=a*b*b,所以Xn=a*b^n。
    因为数据太大,所以使用快速幂加速,long long会乘爆,所以使用慢速乘法。

    #include<iostream>
    #define lon long long
    using namespace std;
    lon m,a,c,x0,n,g,s[3][3],ans[3][3];
    lon slow_mul(lon x,lon y,lon mod)//慢速乘法 
    {
        lon ans=0;
        while(y)
        {
            if(y&1)
            {
                y--;
                ans=(ans+x)%mod;
            }
            y>>=1;
            x=(x+x)%mod;
        }
        return ans;
    }
    void mul(lon p[3][3],lon q[3][3])//快速幂 
    {
        lon tmp[3][3]={0};
        for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
            for(int k=1;k<=2;k++)
            tmp[i][j]=(tmp[i][j]+slow_mul(p[i][k],q[k][j],m))%m;
        for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
          p[i][j]=tmp[i][j];
    }
    void quick_power(lon n)
    {
        lon tmp[3][3];
        for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
          tmp[i][j]=s[i][j];
        while(n)
        {
            if(n&1)
            mul(tmp,s);//因为初始值tmp为s,所以为n-1次幂 ,而不是n次幂。。。。 
            mul(s,s);
            n>>=1;
        }
        for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
          s[i][j]=tmp[i][j];
    }
    int main()
    {
        cin>>m>>a>>c>>x0>>n>>g;
        ans[1][1]=x0,ans[1][2]=c,ans[2][1]=0,ans[2][2]=0;
        s[1][1]=a,s[1][2]=0,s[2][1]=1,s[2][2]=1;
        quick_power(n-1);//为什么是n-1次幂? 
        lon tmp[3][3]={0};
        for(int i=1;i<=2;i++)
          for(int j=1;j<=2;j++)
            for(int k=1;k<=2;k++)
            tmp[i][j]=(tmp[i][j]+slow_mul(ans[i][k],s[k][j],m))%m;
        cout<<tmp[1][1]%g;//输出答案 
        return 0;
    }
  • 相关阅读:
    dubbo
    Executer invokeAll
    java并发编程实战 java并发编程的艺术 阅读随笔
    小程序如何获取指定类名高度
    一些好用的Swift三方框架
    微信小程序checkbox多选传多个参数的操作
    关于xcode出现An unknown error occurred. See the install log for more details安装失败解决办法
    iOS 针对于13.0和暗黑模式出现的适配问题
    iOS UITextField如何禁止输入表情及特殊字符
    判断iPhoneX适配问题
  • 原文地址:https://www.cnblogs.com/cax1165/p/6070923.html
Copyright © 2011-2022 走看看