• BZOJ3240 [Noi2013]矩阵游戏


    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

     

    Description

    婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的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的余数。

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    Input

    一行有六个整数n,m,a,b,c,d。意义如题所述

    Output

    包含一个整数,表示F[n][m]除以1,000,000,007的余数

    Sample Input

    3 4 1 3 2 6

    Sample Output

    85

    HINT

    样例中的矩阵为:

    1 4 7 10

    26 29 32 35

    76 79 82 85



    1<=N,M<=10^1000 000,a<=a,b,c,d<=10^9

     

     

    正解:费马小定理+快速幂+递推公式

    解题报告:

      大多数题解写的都是矩乘+快速幂的,感觉不用那么麻烦,只需要一点点高一课堂上讲过的推出递推式子就可以了。

      推导过程其实挺简单的,就是根据那个式子,先推导出f[i,m]和f[i,1]的关系,然后得到f[i+1,1],再根据新的式子得到f[n+1,1]和f[1,1]的关系,反推得到f[n,m]即可。

      具体推导的话直接复制别人的了,很详细:(参考博客链接:http://www.cnblogs.com/iiyiyi/p/5617598.html)

     

     

      1 //It is made by ljh2000
      2 #include <iostream>
      3 #include <cstdlib>
      4 #include <cstring>
      5 #include <cstdio>
      6 #include <cmath>
      7 #include <algorithm>
      8 #include <ctime>
      9 #include <vector>
     10 #include <queue>
     11 #include <map>
     12 #include <set>
     13 using namespace std;
     14 typedef long long LL;
     15 const int inf = (1<<30);
     16 const int MAXN = 1000011;
     17 const int mod = 1000000007;
     18 const int MOD = 10000000;
     19 int n,m,len;
     20 int k1[200000],k2[200000];
     21 int mi[12]={1,10,100,1000,10000,100000,1000000,10000000,100000000};
     22 char ch[MAXN];
     23 LL a,b,c,d,A,B,ans,ans2,C,D;
     24 //A=c*a^(m-1)
     25 //B=( ( b*c*(a^(m-1)-1) ) / (a-1) )+d
     26 
     27 inline int getint()
     28 {
     29     int w=0,q=0; char c=getchar();
     30     while((c<'0' || c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); 
     31     while (c>='0' && c<='9') w=w*10+c-'0', c=getchar(); return q ? -w : w;
     32 }
     33 inline LL fastpow(LL x,LL y){ 
     34     if(x==1 || y==0) return 1; 
     35     LL base=x,r=1; 
     36     while(y>0) {
     37     if(y&1) r*=base,r%=mod; 
     38     base*=base; base%=mod; y>>=1; 
     39     } 
     40     return r; 
     41 }
     42 inline LL ni(LL x){ return fastpow(x,mod-2); }
     43 inline LL fastpow_m(){
     44     LL res=0; LL mm=1;//对指数取模
     45     for(int i=1;i<=m;i++) res+=mm*k2[i]%(mod-1),mm*=MOD,mm%=(mod-1),res%=(mod-1);
     46     return fastpow(a,res);
     47     /*
     48     LL r=1,base=a; 
     49     while(m) {
     50     if(k2[1]&1) r*=base,r%=mod;
     51     base*=base; base%=mod;
     52     for(int i=m;i>=1;i--) {
     53         if(k2[i]&1) k2[i-1]+=MOD;
     54         k2[i]>>=1;
     55     }
     56     while(k2[m]==0 && m>0) m--;
     57     }
     58     return r;*/
     59 }
     60 
     61 inline LL fastpow_n(LL di){
     62     LL res=0; LL mm=1;//对指数取模
     63     for(int i=1;i<=n;i++) res+=mm*k1[i]%(mod-1),mm*=MOD,mm%=(mod-1),res%=(mod-1);
     64     return fastpow(di,res);
     65     /*
     66     LL r=1,base=di;
     67     while(n) {
     68     if(k1[1]&1) r*=base,r%=mod;
     69     base*=base; base%=mod;
     70     for(int i=n;i>=1;i--) {
     71         if(k1[i]&1) k1[i-1]+=MOD;
     72         k1[i]>>=1;
     73     }
     74     while(k1[n]==0 && n>0) n--;
     75     }
     76     return r;*/
     77 }
     78 
     79 inline void getAB(){    
     80     A=fastpow_m(); A*=ni(a); A%=mod; //A=a^(m-1)    
     81     B=A; B--; B*=b; B%=mod; B*=c; B%=mod;
     82     B*=ni(a-1); B%=mod; B+=d; B%=mod; A*=c; A%=mod; 
     83 }
     84 
     85 inline void over(){
     86     ans-=d; ans+=mod; ans%=mod; ans*=ni(c); ans%=mod;
     87     printf("%lld",ans);
     88 }
     89 
     90 inline void work(){
     91     scanf("%s",ch); len=strlen(ch); n=1; int now=0; 
     92     int gi=0;
     93     for(int i=len-1;i>=0;i--) {
     94     now=now+(ch[i]-'0')*mi[gi];//!!!
     95     gi++;
     96     if(now>=MOD || gi>=8) {
     97         gi=1;//!!!
     98         k1[n]+=now%MOD;
     99         k1[++n]=now/MOD;
    100         now=0;//!!!
    101     }
    102     }
    103     k1[n]+=now; while(k1[n]==0) n--;
    104 
    105     scanf("%s",ch); len=strlen(ch); m=1; now=0;
    106     gi=0;
    107     for(int i=len-1;i>=0;i--) {
    108     now=now+(ch[i]-'0')*mi[gi]; gi++;
    109     if(now>=MOD || gi>=8) {
    110         gi=1;
    111         k2[m]+=now%MOD;
    112         k2[++m]=now/MOD;
    113         now=0;
    114     }
    115     }
    116     k2[m]+=now; while(k2[m]==0) m--;
    117     a=getint(); b=getint(); c=getint(); d=getint();
    118     if(a!=1) {
    119     getAB(); 
    120     if(A!=1) {
    121         ans=fastpow_n(A); ans%=mod;
    122         ans2=ans-1; ans2+=mod; ans2%=mod; ans2*=B; ans2%=mod;
    123         ans2*=ni(A-1); ans2%=mod; ans+=ans2; ans%=mod;
    124     }
    125     else{//特判A==1
    126         LL res=0,mm=1; for(int i=1;i<=n;i++) res+=mm*k1[i]%mod,mm*=MOD,mm%=mod,res%=mod;
    127         ans=res*B; ans++; ans%=mod;
    128     }
    129     over();    
    130     }
    131     else {
    132     D=c*b; D%=mod; LL res=0,mm=1;
    133     for(int i=1;i<=m;i++) res+=mm*k2[i]%mod,mm*=MOD,mm%=mod,res%=mod;
    134     res--; res+=mod; res%=mod; D*=res; D%=mod; D+=d; D%=mod;
    135     if(c==1) {
    136         res=0; mm=1;   for(int i=1;i<=n;i++) res+=mm*k1[i]%mod,mm*=MOD,mm%=mod,res%=mod;
    137         D*=res; D%=mod; ans=D+1;
    138         over();
    139     }
    140     else{
    141         C=fastpow_n(c);
    142         ans=C; C-=1; C*=ni(c-1); C%=mod;
    143         ans+=D*C; ans%=mod;
    144         over();
    145     }
    146     }
    147 }
    148 
    149 int main()
    150 {
    151     work();
    152     return 0;
    153 }
  • 相关阅读:
    GetTickCount 和getTickCount
    载入其他同名源文件导致vs编译错误
    opencv的配置
    VS05错误:部署WEB文件失败
    c++移动文件夹
    opencv2.4.0版本不支持Mat的大小自动调整?
    关于c++中public & private方法调用问题
    c++读取文件夹及子文件夹数据
    深入理解java虚拟机-第四章
    深入理解java虚拟机-第三章
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/5980942.html
Copyright © 2020-2023  润新知