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 }
原文地址:https://www.cnblogs.com/ljh2000-jump/p/5980942.html