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 & y & 1-y & 0 & 0 & y & 1-y\\
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; }