1. 程式人生 > >【BZOJ3240】【NOI2013】矩陣遊戲(數論)

【BZOJ3240】【NOI2013】矩陣遊戲(數論)

char ++i getc getchar() 系列 HP 推導 max long long

【BZOJ3240】【NOI2013】矩陣遊戲(數論)

題面

BZOJ

題解

搞什麽矩陣十進制快速冪加卡常?
直接數學推導不好嗎?
首先觀察如何從每一行的第一個推到最後一個
\(f[i]=a·f[i-1]+b\)
利用數列的一系列知識
我們設\(f[i]+x=a(f[i-1]+x)\)
解出\(x=\frac{b}{a-1}\)
所以\(f[m]=a^{m-1}(f[1]+x)-x\)
也就是\(f[m]=a^{m-1}·f[1]+(a^{m-1}-1)x\)
再把它變到下一行去
\(f'[1]=c·f[m]+d\)
\(f'[1]=ca^{m-1}·f[1]+c(a^{m-1}-1)x+d\)


這樣子,相當於\(A=ca^{m-1}\),\(B=c(a^{m-1}-1)x+d\)
這樣子就是一個重新開始的上面推導的數列了

但是需要註意,當\(a\)\(A\)\(1\)的時候需要特殊判斷一下
所以就是分類討論一下就好了

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector> #include<queue> using namespace std; #define ll long long #define RG register #define MAX 1000100 #define MOD 1000000007 inline int read() { RG int x=0,t=1;RG char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-'
)t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } int n,m,A,B,C,D; char N[MAX],M[MAX]; int get(char *c,int Mod) { int x=0; for(int i=1,l=strlen(c+1);i<=l;++i) x=(1ll*x*10+c[i]-48)%Mod; return x; } int fpow(int a,int b) { int s=1; while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;} return s; } int n1,n2,m1,m2; int main() { scanf("%s%s",N+1,M+1); A=read();B=read();C=read();D=read(); int ans=1; m2=get(M,MOD);m2=(m2+(MOD-1))%MOD; m1=get(M,MOD-1);m1=(m1+(MOD-2))%(MOD-1); n1=get(N,MOD-1);n2=get(N,MOD); if(A!=1) { int x=1ll*B*fpow(A-1,MOD-2)%MOD; B=(1ll*C*(fpow(A,m1)-1+MOD)%MOD*x%MOD+D)%MOD; A=1ll*C*fpow(A,m1)%MOD; if(A!=1) { int x=1ll*B*fpow(A-1,MOD-2)%MOD; ans=(1ll*(1+x)*fpow(A,n1))%MOD; ans=(ans+MOD-x)%MOD; ans=(ans+MOD-D)*1ll*fpow(C,MOD-2)%MOD; printf("%d\n",ans); return 0; } else { ans=(ans+1ll*B*n1)%MOD; ans=(ans+MOD-D)*1ll*fpow(C,MOD-2)%MOD; printf("%d\n",ans); return 0; } } else { A=C;B=(1ll*m2*B%MOD*C%MOD+D)%MOD; if(A!=1) { int x=1ll*B*fpow(A-1,MOD-2)%MOD; ans=(1ll*(1+x)*fpow(A,n1))%MOD; ans=(ans+MOD-x)%MOD; ans=(ans+MOD-D)*1ll*fpow(C,MOD-2)%MOD; printf("%d\n",ans); return 0; } else { ans=(ans+1ll*B*n2)%MOD; ans=(ans+MOD-D)*1ll*fpow(C,MOD-2)%MOD; printf("%d\n",ans); return 0; } } printf("%d\n",ans); return 0; }

【BZOJ3240】【NOI2013】矩陣遊戲(數論)