zoukankan      html  css  js  c++  java
  • [Noi2013]矩阵游戏

    来自FallDream的博客,未经允许,请勿转载,谢谢。


    婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储)。她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式:

    F[1][1]=1

    F[i,j]=a*F[i][j-1]+b (j!=1)

    F[i,1]=c*F[i-1][m]+d (i!=1)

    递推式中a,b,c,d都是给定的常数。

    现在婷婷想知道F[n][m]的值是多少,请你帮助她。由于最终结果可能很大,你只需要输出F[n][m]除以1,000,000,007的余数。

    直接矩阵乘法貌似可以卡过  看评测机速度233

    但是发现你只要记下ans=a*x+b 的a和b就行了 ,这样操作数量减少了一半,500ms左右就能过

    讲讲正解 先考虑一行  假设m=4,x是首项,那么F[m]= a(a(a(x)+b)+b)+b 发现F[m]是一个等比数列加上一个 a^(m-1)*x .直接套用等比数列求和公式即可。

    再考虑n,发现我可以把前面那个式子同样表示成Ax+B的形式,然后每次跳一行只是乘上C再加上D罢了,同样可以表示成等比数列 所以用同样的方法就可以解出答案

    注意特判比为1的情况。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define mod 1000000007
    #define getchar() (*S++)
    char BB[1<<26],*S=BB;
    using namespace std;
    inline int read()
    {
        int x = 0; char ch = getchar();
        while(ch < '0' || ch > '9') ch = getchar();
        while(ch >= '0' && ch <= '9')x = (x<<1)+(x<<3) + ch - '0',ch = getchar();
        return x;
    }
    
    char n[1000005],m[1000005];
    int a,b,c,d,A=0,B=0,C=0,D=0,len1=0,len2=0,ans=0;
     
    int pow(int x,int k,int P)
    {
        int sum=1;
        for(;k;k>>=1,x=1LL*x*x%P)
            if(k&1) sum=1LL*sum*x%P;
        return sum;
    }
     
    int main()
    {
        fread(BB,1,1<<26,stdin);
        do n[++len1]=getchar(); while(n[len1]!=' ');--len1;
        do m[++len2]=getchar(); while(m[len2]!=' ');--len2;
        a=read();b=read();c=read();d=read();
        for(register int i=1;i<=len2;++i) 
            A=(1LL*A*10+m[i]-'0')%(mod-1),
            B=(1LL*B*10+m[i]-'0')%mod;        
        if(a==1) A=1,B=1LL*(B+mod-1)*b%mod;
        else  B=1LL*b*((pow(a,A+mod-2,mod)+mod-1)%mod)%mod*pow(a-1,mod-2,mod)%mod,A=pow(a,A+mod-2,mod);
        ans=(1LL*A+B)%mod;
        for(register int i=1;i<=len1;++i) 
            C=(1LL*C*10+n[i]-'0')%(mod-1),
            D=(1LL*D*10+n[i]-'0')%mod;    
        c=1LL*A*c%mod,d=(1LL*A*d%mod+B)%mod;
        if(c==1) ans=(ans+1LL*(D+mod-1)*d%mod)%mod;
        else ans=(1LL*d%mod*((pow(c,C+mod-2,mod)+mod-1)%mod)%mod*pow(c-1,mod-2,mod)%mod+1LL*ans*pow(c,C+mod-2,mod)%mod)%mod;
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    小程序对于华为Oppo的canvas二维码渲染数据量大
    SonarQube代码质量管理工具的升级(sonarqube6.2 + sonar-scanner-2.8 + MySQL5.6+)
    SonarQube代码质量管理工具安装与使用(sonarqube5.1.2 + sonar-runner-dist-2.4 + MySQL5.x)
    在try-catch机制优化IO流关闭时,OutputStreamWriter 数据流被截断
    Java中日期格式化SimpleDateFormat类包含时区的处理方法
    彻底删除mysql服务(清理注册表)
    PHP7新特性的介绍
    RESTful架构详解
    php-config 介绍
    用 phpize 编译共享 PECL 扩展库
  • 原文地址:https://www.cnblogs.com/FallDream/p/noi2013d2t1.html
Copyright © 2011-2022 走看看