\(\mathcal{Description}\)

  有 \(n\) 个黑盒,第 \(i\) 个黑盒可以让输入变量以 \(p_i\) 的概率保持不变,以 \(\frac{1-p_i}2\) 的概率加一或减一。称一次从 \(i\) 开始的游戏为:初始变量的值为 \(0\),从 \(i\) 开始,将变量依次输入 \(i,i+1,\dots,n,1,2,\dots,n,\dots\),直到变量的绝对值大于 \(m\)。处理 \(q\) 次操作:

  1. 求此时一次从某个 \(i\) 开始的游戏期望经过多少个黑盒。答案模 \((10^9+7)\);
  2. 修改某个 \(p_i\) 的值。

  \(n,q\le10^5\),\(m\le5\)。

\(\mathcal{Solution}\)

  DP 是平凡的:令 \(f_{i,j}\) 表示绝对值为 \(j\) 的变量将要输入第 \(i\) 个黑盒时,期望还能经过多少黑盒。那么

\[f_{i,j}=\begin{cases}
1+p_if_{i+1,j}+(1-p_i)f_{i+1,j+1}&j=0\\
1+p_if_{i+1,j}+\frac{1-p_i}{2}(f_{i+1,j+1}+f_{i+1,j-1})&j>0
\end{cases}.
\]

  紧接着,你看我久违地把 DP 状态写成下标的形式就知道,应用整体思想,令

\[F_i=\begin{bmatrix}f_{0,0}\\
\vdots\\
f_{m,0}\\
1
\end{bmatrix},
\]

据此不难得出

\[F_i=M_iF_{i+1},
\]

其中 \(M_i\) 是一个仅与 \(p_i\) 有关的转移矩阵。鉴于答案要求 \(f_{i,0}\),我们只需要关心某个特定的 \(F_i\) 的值。从方程角度考虑,发现

\[\begin{aligned}
F_i&=M_iF_{i+1}\\
&=M_iM_{i+1}\cdots M_{n}F_1\\
&=M_iM_{i+1}\cdots M_{n}M_1M_2\cdots M_{i-1}F_i
\end{aligned}.
\]

所以说用线段树维护 \(M\) 的区间积,快速求出 \(F_i=AF_i\) 中的 \(A\),然后 \(\mathcal O(m^3)\) 消元就行。最终最劣复杂度为 \(\mathcal O(qm^3\log n)\)。

\(\mathcal{Code}\)

/* Clearink */

#include <cstdio>
#include <cassert>
#include <cstring>
#include <iostream> #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
#define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i ) inline int rint() {
int x = 0, f = 1, s = getchar();
for ( ; s < '0' || '9' < s; s = getchar() ) f = s == '-' ? -f : f;
for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' );
return x * f;
} template<typename Tp>
inline void wint( Tp x ) {
if ( x < 0 ) putchar( '-' ), x = -x;
if ( 9 < x ) wint( x / 10 );
putchar( x % 10 ^ '0' );
} const int MAXN = 1e5, MAXK = 5, MOD = 1e9 + 7, INV2 = MOD + 1 >> 1;
int n, m /* i.e. k */, q; inline int mul( const long long a, const int b ) { return a * b % MOD; }
inline int sub( int a, const int b ) { return ( a -= b ) < 0 ? a + MOD : a; }
inline void subeq( int& a, const int b ) { ( a -= b ) < 0 && ( a += MOD ); }
inline int add( int a, const int b ) { return ( a += b ) < MOD ? a : a - MOD; }
inline void addeq( int& a, const int b ) { ( a += b ) >= MOD && ( a -= MOD ); }
inline int mpow( int a, int b ) {
int ret = 1;
for ( ; b; a = mul( a, a ), b >>= 1 ) ret = mul( ret, b & 1 ? a : 1 );
return ret;
} struct Matrix {
static const int MAXS = MAXK + 1;
int mat[MAXS + 1][MAXS + 1]; Matrix(): mat{} {} // !!! inline int* operator [] ( const int k ) { return mat[k]; } friend inline Matrix operator * ( const Matrix& u, const Matrix& v ) {
Matrix ret;
rep ( i, 0, MAXS ) rep ( k, 0, MAXS ) rep ( j, 0, MAXS ) {
addeq( ret[i][j], mul( u.mat[i][k], v.mat[k][j] ) );
}
return ret;
}
}; inline void setTMat( Matrix& u, const int p ) {
u = Matrix();
u[0][0] = p;
rep ( i, 0, m + 1 ) u[m + 1][i] = 0, u[i][m + 1] = 1;
if ( !m ) return ;
u[0][1] = sub( 1, p ); int cp = mul( INV2, sub( 1, p ) );
rep ( i, 1, m ) {
u[i][i] = p, u[i][i - 1] = cp;
if ( i + 1 <= m ) u[i][i + 1] = cp;
}
} struct SegmentTree {
Matrix sum[MAXN << 2]; inline void build( const int u, const int l, const int r ) {
if ( l == r ) {
int a = rint();
setTMat( sum[u], mul( a, mpow( rint(), MOD - 2 ) ) );
return ;
}
int mid = l + r >> 1;
build( u << 1, l, mid ), build( u << 1 | 1, mid + 1, r );
sum[u] = sum[u << 1] * sum[u << 1 | 1];
} inline void modify( const int u, const int l, const int r,
const int x, const int p ) {
if ( l == r ) return setTMat( sum[u], p );
int mid = l + r >> 1;
if ( x <= mid ) modify( u << 1, l, mid, x, p );
else modify( u << 1 | 1, mid + 1, r, x, p );
sum[u] = sum[u << 1] * sum[u << 1 | 1];
} inline Matrix query( const int u, const int l, const int r,
const int ql, const int qr ) {
if ( ql <= l && r <= qr ) return sum[u];
int mid = l + r >> 1;
if ( qr <= mid ) return query( u << 1, l, mid, ql, qr );
if ( mid < ql ) return query( u << 1 | 1, mid + 1, r, ql, qr );
return query( u << 1, l, mid, ql, qr )
* query( u << 1 | 1, mid + 1, r, ql, qr );
}
} sgt; inline void gauss( const int s, int a[MAXK + 1][MAXK + 2], int* x ) {
rep ( i, 0, s ) {
int p;
rep ( j, i, s ) if ( a[j][i] ) { p = j; break; }
if ( i != p ) std::swap( a[i], a[p] );
assert( a[i][i] ); int iv = mpow( a[i][i], MOD - 2 );
rep ( j, i + 1, s ) {
int t = mul( a[j][i], iv );
rep ( k, i, s + 1 ) subeq( a[j][k], mul( t, a[i][k] ) );
}
} per ( i, s, 0 ) {
x[i] = mul( a[i][s + 1], mpow( a[i][i], MOD - 2 ) );
per ( j, i - 1, 0 ) subeq( a[j][s + 1], mul( x[i], a[j][i] ) );
}
} inline int solve( Matrix& u ) {
int a[MAXK + 1][MAXK + 2], x[MAXK + 1];
memset( a, 0, sizeof a ); rep ( i, 0, m ) {
a[i][i] = MOD - 1;
rep ( j, 0, m ) addeq( a[i][j], u[i][j] );
a[i][m + 1] = sub( 0, u[i][m + 1] );
} gauss( m, a, x );
return x[0];
} int main() {
freopen( "samsara.in", "r", stdin );
freopen( "samsara.out", "w", stdout ); n = rint(), m = rint(), q = rint();
sgt.build( 1, 1, n ); for ( int op, i, a, b; q--; ) {
op = rint(), i = rint();
if ( op == 1 ) {
Matrix tmat;
if ( i == 1 ) tmat = sgt.query( 1, 1, n, 1, n );
else {
tmat = sgt.query( 1, 1, n, i, n )
* sgt.query( 1, 1, n, 1, i - 1 );
}
wint( solve( tmat ) ), putchar( '\n' );
} else {
a = rint(), b = rint();
sgt.modify( 1, 1, n, i, mul( a, mpow( b, MOD - 2 ) ) );
}
}
return 0;
}

Solution -「多校联训」轮回的更多相关文章

  1. Solution -「多校联训」排水系统

    \(\mathcal{Description}\)   Link.   在 NOIP 2020 A 的基础上,每条边赋权值 \(a_i\),随机恰好一条边断掉,第 \(i\) 条段的概率正比于 \(a ...

  2. Solution -「多校联训」I Love Random

    \(\mathcal{Description}\)   给定排列 \(\{p_n\}\),可以在其上进行若干次操作,每次选取 \([l,r]\),把其中所有元素变为原区间最小值,求能够得到的所有不同序 ...

  3. Solution -「多校联训」签到题

    \(\mathcal{Description}\)   Link.   给定二分图 \(G=(X\cup Y,E)\),求对于边的一个染色 \(f:E\rightarrow\{1,2,\dots,c\ ...

  4. Solution -「多校联训」朝鲜时蔬

    \(\mathcal{Description}\)   Link.   破案了,朝鲜时蔬 = 超现实树!(指写得像那什么一样的题面.   对于整数集 \(X\),定义其 好子集 为满足 \(Y\sub ...

  5. Solution -「多校联训」消失的运算符

    \(\mathcal{Description}\)   Link.   给定长度为 \(n\) 的合法表达式序列 \(s\),其中数字仅有一位正数,运算符仅有 - 作为占位.求将其中恰好 \(k\) ...

  6. Solution -「多校联训」假人

    \(\mathcal{Description}\)   Link.   一种物品有 长度 和 权值 两种属性,现给定 \(n\) 组物品,第 \(i\) 组有 \(k_i\) 个,分别为 \((1,a ...

  7. Solution -「多校联训」古老的序列问题

    \(\mathcal{Description}\)   Link.   给定序列 \(\{a_n\}\),和 \(q\) 次形如 \([L,R]\) 的询问,每次回答 \[\sum_{[l,r]\su ...

  8. Solution -「多校联训」Sample

    \(\mathcal{Description}\)   Link   (稍作简化:)对于变量 \(p_{1..n}\),满足 \(p_i\in[0,1],~\sum p_i=1\) 时,求 \(\ma ...

  9. Solution -「多校联训」光影交错

    \(\mathcal{Description}\)   Link.   一个游戏包含若干次卡牌抽取,每次以 \(p_l\) 的概率得到 \(+1\),\(p_d\) 的概率得到 \(-1\),否则得到 ...

随机推荐

  1. [Docker] 在CentOS6.8 安装 Docker

    运行docker Linux内核版本需要在3.8以上,针对centos6.5 内核为2.6的系统需要先升级内核.不然会特别卡,退出容器. # 查看当前版本: cat /etc/issue # 导入pu ...

  2. SpringBoot学习笔记三之表述层

    注:图片如果损坏,点击文章链接:https://www.toutiao.com/i6803355920697917965/ 首先配置learn-admin-webui中的web.xml文件 配置Con ...

  3. SYCOJ1793

    题目-统计单词前缀数 (shiyancang.cn) 1 #include<bits/stdc++.h> 2 using namespace std; 3 map<string,in ...

  4. 机器学习&恶意代码动态检测

    目录 写在前面 1 基于API调用的统计特征 2 API序列特征 3 API调用图 4 基于行为的特征 references: 写在前面 对恶意程序动态检测方法做了概述, 关于方法1和2可以参考阿里云 ...

  5. 【Android】安卓四大组件之Activity(二)

    [Android]安卓四大组件之Activity(二) 前言 在这篇文章之前,我已经写过了一篇有关Activity的内容,是关于activity之间的页面跳转和数据传递,而这篇文章着重强调的是Acti ...

  6. java继承基础内容

    1 /* 2 * 继承的好处: 3 * 1,提高了代码的复用性. 4 * 2,让类与类之间产生了关系,给第三个特征多态提供了前提. 5 * 6 * 7 * java中支持单继承.不直接支持多继承,但对 ...

  7. 什么是Listener监听器

    什么是Listener监听器 1,Listener 监听器它是JavaWeb的三大组件之一.JavaWeb的三大组件:Servlet程序,Filter过滤器,Listener监听器. 2,Listen ...

  8. java多态转型II

    1 package face_09; 2 3 /* 4 * 毕老师和毕姥爷的故事. 5 */ 6 class 毕姥爷 { 7 void 讲课() { 8 System.out.println(&quo ...

  9. java-异常概述及体系

    1 package p1.exception; 2 3 4 /* 5 * 异常:是在运行时期发生的不正常情况. 6 * 7 * 8 * 在java中用类的形式对不正常情况进行了描述和封装对象. 9 * ...

  10. Excel与MySQL数据库的导入与导出

    应用场景 在许多时候,我们希望数据能够很好地在各个系统之间转移,同时便于非专业人员阅读,如果程序员一点点打字导出的话,不知道要打到什么时候,于是我们便采用日常工作中常用的Excel表格来作为媒介,将数 ...