【费马小定理+快速幂+逆元】BZOJ3240-[NOI2013]矩阵游戏
【题目大意】
若用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]。
【思路】
磨了一个早上,然而UOJ上的额外数据还没有过去..BZOJ上已AC先放上来,后续慢慢磨……
*还有一点,最后输出答案的时候要先+MOD再%MOD。
*MOD要勤快一点,不然会爆。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define MOD 1000000007 6 using namespace std; 7 typedef long long ll; 8 const int MAXN=1000000+5; 9 struct node 10 { 11 ll uni,ord;//uni表示a≠1,ord表示a=1 12 }n,m; 13 ll a,b,c,d; 14 15 ll quick(ll x,ll p) 16 { 17 ll res=p,retu=1,now=x; 18 while (res>0) 19 { 20 if (res&1) retu=(retu*now) % MOD; 21 now=(now*now) % MOD; 22 res>>=1; 23 } 24 return retu; 25 } 26 27 ll ni(ll x) 28 { 29 return quick(x,MOD-2); 30 } 31 32 node get_value(char str[]) 33 { 34 int len=strlen(str); 35 node ret=(node){0,0}; 36 for (int i=0;i<len;i++) 37 { 38 ret.uni=((ret.uni*10)%(MOD-1)+str[i]-'0')%(MOD-1); 39 ret.ord=((ret.ord*10)%MOD+str[i]-'0')%MOD; 40 } 41 return ret; 42 } 43 44 void init() 45 { 46 char strm[MAXN],strn[MAXN]; 47 scanf("%s%s",strn,strm); 48 n=get_value(strn); 49 m=get_value(strm); 50 scanf("%lld%lld%lld%lld",&a,&b,&c,&d); 51 } 52 53 void get_ans() 54 { 55 ll f;//=f[n+1][1] 56 if (a==1) 57 { 58 ll D=((((c*(m.ord-1))%MOD)*b)%MOD+d)%MOD; 59 if (c==1) f=(1+n.ord*D)%MOD; 60 else 61 { 62 ll cn=quick(c,n.uni); 63 f=(cn+(D*(cn-1)*ni(c-1)%MOD))%MOD; 64 } 65 } 66 if (a!=1) 67 { 68 ll am=quick(a,m.uni-1); 69 ll A=(am*c)%MOD; 70 ll B=(((((b*c)%MOD*(am-1))%MOD*ni(a-1)))%MOD+d)%MOD; 71 ll An=quick(A,n.uni); 72 f=An+((B*(An-1)%MOD)*ni(A-1))%MOD; 73 } 74 printf("%lld",((f-d)*ni(c)%MOD+MOD)%MOD); 75 } 76 77 int main() 78 { 79 init(); 80 get_ans(); 81 return 0; 82 }