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
Sample Output
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 }