bzoj 3240: [Noi2013]矩阵游戏
2018-07-14 19:47
363 查看
Description
婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储)。她生成的这个矩阵满足一个神奇的性质:若用F[i][j]来表示矩阵中第i行第j列的元素,则F[i][j]满足下面的递推式:F[1][1]=1
F[i,j]=aF[i][j-1]+b (j!=1)
F[i,1]=cF[i-1][m]+d (i!=1)
递推式中a,b,c,d都是给定的常数。
现在婷婷想知道F
[m]的值是多少,请你帮助她。由于最终结果可能很大,你只需要输出F
[m]除以1,000,000,007的余数。
Solution
这题可以暴力矩乘跑过去设初始矩阵为 \(A\),列转移矩阵为 \(B\),行转移矩阵为 \(C\)
那么答案就是 \(A*(B^{m-2}*C)^{n-2}*B\)
矩乘要用十进制快速幂,和二进制差不多,这一位是多少就乘多少次就行了
#include<bits/stdc++.h> using namespace std; #define RG register const int mod=1e9+7; struct mat{ int a[2][2]; mat(){memset(a,0,sizeof(a));} inline mat operator *(const mat &p){ mat ret; for(RG int i=0;i<2;i++) for(RG int j=0;j<2;j++) for(RG int k=0;k<2;k++) ret.a[i][j]=(ret.a[i][j]+1ll*a[i][k]*p.a[k][j])%mod; return ret; } }; const int N=1e6+10; char s1 ,s2 ; inline void ksm(mat &S,mat T,int k){ while(k){ if(k&1)S=S*T; T=T*T;k>>=1; } } inline mat mul(mat S,mat T,char *s,int len){ for(RG int i=len;i>=1;i--){ ksm(S,T,s[i]-48); if(i>1)ksm(T,T,9); } return S; } int main(){ freopen("pp.in","r",stdin); freopen("pp.out","w",stdout); scanf("%s%s",s2+1,s1+1); int a,b,c,d,len; cin>>a>>b>>c>>d; if(strlen(s1+1)==1 && s1[1]=='1' && strlen(s2+1)==1 && s2[1]=='1') puts("1"),exit(0); mat S,T,O,R; if(strlen(s1+1)==1 && s1[1]=='1'){ S.a[0][0]=S.a[0][1]=1;S.a[1][0]=S.a[1][1]=0; T.a[0][0]=c;T.a[1][0]=d;T.a[1][1]=1; len=strlen(s2+1);s2[len]--; for(int i=len;i>=1;i--)if(s2[i]<'0')s2[i]+=10,s2[i-1]--;else break; S=mul(S,T,s2,len); cout<<S.a[0][0]<<endl; return 0; } if(strlen(s2+1)==1 && s2[1]=='1'){ S.a[0][0]=S.a[0][1]=1;S.a[1][0]=S.a[1][1]=0; T.a[0][0]=a;T.a[1][0]=b;T.a[1][1]=1; len=strlen(s1+1);s1[len]--; for(int i=len;i>=1;i--)if(s1[i]<'0')s1[i]+=10,s1[i-1]--;else break; S=mul(S,T,s1,len); cout<<S.a[0][0]<<endl; return 0; } S.a[0][0]=a;S.a[1][0]=b;S.a[1][1]=1; T.a[0][0]=c;T.a[1][0]=d;T.a[1][1]=1;T.a[0][1]=0; len=strlen(s1+1);s1[len]-=2; for(int i=len;i>=1;i--)if(s1[i]<'0')s1[i]+=10,s1[i-1]--;else break; S=mul(S,S,s1,len);O=S;S=S*T; len=strlen(s2+1);s2[len]-=2; for(int i=len;i>=1;i--)if(s2[i]<'0')s2[i]+=10,s2[i-1]--;else break; S=mul(S,S,s2,len); T.a[0][0]=T.a[0][1]=1;T.a[1][0]=T.a[1][1]=0; S=T*S;S=S*O; cout<<S.a[0][0]<<endl; return 0; }
相关文章推荐
- (十进制高速幂+矩阵优化)BZOJ 3240 3240: [Noi2013]矩阵游戏
- BZOJ 3240([Noi2013]矩阵游戏-费马小定理【矩阵推论】-%*s-快速读入)
- bzoj 3240 [Noi2013]矩阵游戏
- 【BZOJ3240】【UOJ124】【NOI2013】矩阵游戏
- [BZOJ 3240][Noi2013]矩阵游戏:逆元+递推
- [BZOJ3240][NOI2013]矩阵游戏
- [BZOJ3240][NOI2013]矩阵游戏(数论+矩乘)
- [BZOJ 3240][NOI 2013]矩阵游戏(数学+乘法逆元)
- BZOJ 3240: [Noi2013]矩阵游戏 矩阵乘法 费马小定理
- BZOJ3240 [Noi2013]矩阵游戏
- BZOJ 3240([Noi2013]矩阵游戏-费马小定理【矩阵推论】-%*s-快速读入)
- BZOJ 3240 [Noi2013]矩阵游戏 ——费马小定理 快速幂
- bzoj 3240: [Noi2013]矩阵游戏 矩阵乘法+十进制快速幂+常数优化
- 【BZOJ3240】【UOJ#124】【NOI2013】矩阵游戏
- 【BZOJ】3240: [Noi2013]矩阵游戏
- 【费马小定理+快速幂+逆元】BZOJ3240-[NOI2013]矩阵游戏
- bzoj 3240: [Noi2013]矩阵游戏
- BZOJ 3240: [Noi2013]矩阵游戏
- 【BZOJ】【3240】【NOI2013】矩阵游戏
- [BZOJ3240][Noi2013]矩阵游戏 && 快速幂