• 【NOI2013T4】矩阵游戏-矩阵优化+十进制快速幂


    测试地址:矩阵游戏

    做法:观察递推式,很明显可以用矩阵优化,设矩阵C={a b 0 1},D={c d 0 1},所以F[1][m]=C^(m-1)*{1 1},再推出F[2][1]=D*C^(m-1)*{1 1},数学归纳得F[n][1]=(D*C^(m-1))^(n-1)*{1 1},所以F[n][m]=C^(m-1)*(D*C^(m-1))^(n-1)*{1 1},于是问题就转化为求矩阵快速幂,然而n和m达到10^1000000,所以计算n-1和m-1时要用到一点高精度运算(这个不会...你还来看这个干什么),而且要使用十进制快速幂,即可节省进制转换的时间,复杂度O(lgN)。其实还可以加一点常数优化,注意到计算时2*2矩阵的第二排都是“0 1”,所以我们可以直接省略这个信息,这样矩阵乘法就变成这样一个运算:{a b}*{c d}={a*c a*d+b},优化了常数。

    以下是本人代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define mod 1000000007
    using namespace std;
    char sn[1000010],sm[1000010];
    long long a,b,c,d;
    struct hd {int s[1000010],len;} n,m;
    struct mat {long long a,b;} A[1000010],C,ANS;
    
    mat mult(mat A,mat B)
    {
      mat S;
      S.a=(A.a*B.a)%mod;
      S.b=((A.a*B.b)%mod+A.b)%mod;
      return S;
    }
    
    mat power(hd s)
    {
      mat S;
      S.a=1,S.b=0;
      for(int i=s.len-1;i>=0;i--)
      {
        for(int j=1;j<=s.s[i];j++)
    	  S=mult(S,A[s.len-i-1]);
      }
      return S;
    }
    
    int main()
    {
      scanf("%s%s%lld%lld%lld%lld",sn,sm,&a,&b,&c,&d);
      n.len=strlen(sn),m.len=strlen(sm);
      for(int i=0;i<n.len;i++) n.s[i]=sn[i]-'0';
      for(int i=0;i<m.len;i++) m.s[i]=sm[i]-'0';
      n.s[n.len-1]--,m.s[m.len-1]--;
      for(int i=n.len-1;i>=0;i--)
      {
        if (n.s[i]<0)
    	{
    	  n.s[i]=9;
    	  n.s[i-1]--;
    	}
    	else break;
      }
      for(int i=m.len-1;i>=0;i--)
      {
        if (m.s[i]<0)
    	{
    	  m.s[i]=9;
    	  m.s[i-1]--;
    	}
    	else break;
      }
      
      A[0].a=a,A[0].b=b;
      for(int i=1;i<=1000001;i++)
      {
        A[i]=A[i-1];
        for(int j=1;j<=9;j++)
    	  A[i]=mult(A[i],A[i-1]);
      }
      
      C=power(m);
      A[0].a=c,A[0].b=d;
      A[0]=mult(A[0],C);
      for(int i=1;i<=1000001;i++)
      {
        A[i]=A[i-1];
        for(int j=1;j<=9;j++)
    	  A[i]=mult(A[i],A[i-1]);
      }
      ANS=mult(C,power(n));
      
      printf("%lld",(ANS.a+ANS.b)%mod);
      
      return 0;
    }
    


  • 相关阅读:
    node.js基础
    JQuery Ajax实例
    数组的模3特性
    浅析Java抽象类和接口的比较
    乐于分享是促进程序员进步非常重要的一个关键点【转载】
    网络图片的加载
    听一下牛人是怎样自学MIT计算机系全部课程的[转]
    我们为什么活着?别在20岁的时候过40岁的生活【转】
    根据字体多少使UILabel自动调节尺寸
    一个博士生学位论文致谢部分
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793765.html
Copyright © 2020-2023  润新知