2020/8/1 模擬賽 Day5 T3 power
Description
機器人小 E 是博士的助手, 現在它需要幫助博士收集製造新機器需要的能量.
小 E 的任務在一個長度為 $N$ 的序列上進行, 初始時刻小 E 在 $0$ 號點, 效率 $Q$ 為 $0$, 每一次它會向右移動一個位置到達編號加一的點, 並且在這個 瞬間小 E 的效率會變化, 具體地:
- 若效率變化以前等於 $0$, 則 $Q$ 有 $x$ 的概率加一, $1-x$ 的概率不變.
- 若效率變化以前等於 $L$, 則 $Q$ 有 $y$ 的概率減一, $1-y$ 的概率不變.
- 其他情況下, $Q$ 有 $x$ 的概率加一, $y$ 的概率減一, $1-x-y$ 的概率不變.
小 E 在到一個點後能獲得 $QA+B$ 的能量, 到 $N$ 號點後收集結束.
現在博士想知道, 期望意義下小 E 能夠收集多少能量, 對 $10^9 +7$ 取模。
Solution
矩陣維護字首和
假設$L=3$,此時構造矩陣$F$
$$\begin{bmatrix}
1-x & x & 0 & 0 & 1-x & x & 0 & 0\\
y & 1-x-y & x & 0 & y & 1-x-y & x & 0\\
0 & y & 1-x-y & x & 0 & y & 1-x-y & x\\
0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\
0 & 0 & 0 & 0 & 0 & 1 & 0 & 0\\
0 & 0 & 0 & 0 & 0 & 0 & 1 & 0\\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 1
\end{bmatrix}$$
矩陣分割為4個部分:
- 左上部分:轉移矩陣,$F_{i,j}$儲存效率從$i$變為$j$的概率
- 右上部分:同左上部分,之後將儲存概率的字首和
- 左下部分:空
- 右下部分:單位矩陣
再構造初始矩陣$G$
$$\begin{bmatrix}
1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\
0 & 0 & 0 & 0 & 0 & 0 & 0 & 0
\end{bmatrix}$$
$G$的意義為初始時效率為0,所以$G_{0,0}$=1
計算$F\cdot G^n$,第$0$行的第$L+1$至$2L+1$列儲存最終效率為列數$-L-1$的字首和,按照題中所給公式計算。
為什麼維護了字首和?
因為$F$矩陣左上部分與$G$矩陣左上部分相乘作為結果矩陣的左上部分表示一步移動之後的各種概率
$F$矩陣左上部分與$G$矩陣右上部分相乘作為結果矩陣右上部分的加數表示本步移動的各種概率
$F$矩陣右上部分與$G$矩陣右下部分相乘作為結果矩陣右上部分的加數表示之前移動的各種概率
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; long long n,a,b,l,x,y,ans; const long long mod=1000000007; struct Matrix { long long a[120][120]; Matrix() { memset(a,0,sizeof(a)); } Matrix operator * (const Matrix &z)const { Matrix ret; for(int i=0;i<=2*l+1;i++) { for(int j=0;j<=2*l+1;j++) { for(int k=0;k<=2*l+1;k++) { (ret.a[i][j]+=a[i][k]*z.a[k][j])%=mod; } } } return ret; } }F,G; inline long long read() { long long f=1,w=0; char ch=0; while(ch<'0'||ch>'9') { if(ch=='-') { f=-1; } ch=getchar(); } while(ch>='0'&&ch<='9') { w=(w<<1)+(w<<3)+ch-'0'; ch=getchar(); } return f*w; } Matrix operator ^ (Matrix z,long long p) { Matrix ret; for(int i=0;i<=2*l+1;i++) { ret.a[i][i]=1; } while(p) { if(p&1) { ret=ret*z; } z=z*z; p>>=1; } return ret; } long long ksm(long long A,long long p) { long long ret=1ll; while(p) { if(p&1) { (ret*=A)%=mod; } (A*=A)%=mod; p>>=1; } return ret; } int main() { freopen("power.in","r",stdin); freopen("power.out","w",stdout); n=read(); a=read(); b=read(); l=read(); x=read(); y=read(); x=x*ksm(100,mod-2)%mod; y=y*ksm(100,mod-2)%mod; F.a[0][0]=1; for(int i=0;i<=l;i++) { int cnt=1; if(i<l) { G.a[i][i+1+l+1]=G.a[i][i+1]=x; cnt=(cnt-x+mod)%mod; } if(i>0) { G.a[i][i-1+l+1]=G.a[i][i-1]=y; cnt=(cnt-y+mod)%mod; } G.a[i][i+l+1]=G.a[i][i]=cnt; } for(int i=l+1;i<=2*l+1;i++) { G.a[i][i]=1; } F=F*(G^n); for(int i=l+1;i<=2*l+1;i++) { (ans+=F.a[0][i]*((i-l-1)*a%mod+b))%=mod; } printf("%lld\n",ans); return 0; }power