日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[UOJ299][CTSC2017] 游戏

發布時間:2023/12/3 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [UOJ299][CTSC2017] 游戏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

【CTSC2017】游戲

problem

UOJ299

solution

定義 Xi:X_i:Xi?: 當前已知條件第 iii 局的狀態 1/01/01/0(勝/敗)。

Xi=CiX_i=C_iXi?=Ci? 記為事件 AiA_iAi?

假設現在已知條件共有 sss 個,即:第 k1~sk_{1\sim s}k1s? 局的勝負狀態。

期望不妨拆成求和每一局獲勝的概率。

那么答案為 ∑i=1nP(Xi=1∣Ak1Ak2...Aks)\sum_{i=1}^nP(X_i=1\Big|A_{k_1}A_{k_2}...A_{ks})i=1n?P(Xi?=1?Ak1??Ak2??...Aks?)

P(Xi=1∣Ak1Ak2...Aks)=P(Xi=1?Ak1...Aks)P(Ak1...Aks)P(X_i=1\Big|A_{k_1}A_{k_2}...A_{ks})=\frac{P(X_i=1·A_{k_1}...A_{k_s})}{P(A_{k_1}...A_{k_s})}P(Xi?=1?Ak1??Ak2??...Aks?)=P(Ak1??...Aks??)P(Xi?=1?Ak1??...Aks??)?

P(Ak1...Aks)=P(Ak1)P(Ak2∣Ak1)P(Ak3∣Ak1Ak2)...P(Aks∣Ak1...Aks?1)P(A_{k_1}...A_{k_s})=P(A_{k_1})P(A_{k_2}|A_{k_1})P(A_{k_3}|A_{k_1}A_{k_2})...P(A_{k_s}|A_{k_1}...A_{k_{s-1}})P(Ak1??...Aks??)=P(Ak1??)P(Ak2??Ak1??)P(Ak3??Ak1??Ak2??)...P(Aks??Ak1??...Aks?1??)

因為每一局的勝負概率只和上一局有關,所以 P(Ak3∣Ak1Ak2)=P(Ak3∣Ak2)P(A_{k_3}|A_{k_1}A_{k_2})=P(A_{k_3}|A_{k_2})P(Ak3??Ak1??Ak2??)=P(Ak3??Ak2??)

即,P(Ak1...Aks)=P(Ak1)P(Ak2∣Ak1)P(Ak3∣Ak2)...P(Aks∣Aks?1)P(A_{k_1}...A_{k_s})=P(A_{k_1})P(A_{k_2}|A_{k_1})P(A_{k_3}|A_{k_2})...P(A_{k_s}|A_{k_{s-1}})P(Ak1??...Aks??)=P(Ak1??)P(Ak2??Ak1??)P(Ak3??Ak2??)...P(Aks??Aks?1??)

假設 k1<k2<...<kj<i<kj+1<...<ksk_1<k_2<...<k_j<i<k_{j+1}<...<k_sk1?<k2?<...<kj?<i<kj+1?<...<ks?

類似地,P(Xi=1Ak1...Aks)=P(Ak1)...P(Akj∣Xi=1)P(Xi=1∣Akj+1)...P(Aks∣Aks?1)P(X_i=1A_{k_1}...A_{k_s})=P(A_{k_1})...P(A_{k_j}|X_i=1)P(X_i=1|A_{k_{j+1}})...P(A_{k_s}|A_{k_{s-1}})P(Xi?=1Ak1??...Aks??)=P(Ak1??)...P(Akj??Xi?=1)P(Xi?=1Akj+1??)...P(Aks??Aks?1??)

所以 P(Xi=1∣Ak1Ak2...Aks)=P(Akj∣Xi=1)P(Xi=1∣Akj+1)P(Akj+1∣Akj)P(X_i=1\Big|A_{k_1}A_{k_2}...A_{ks})=\frac{P(A_{k_j}|X_i=1)P(X_i=1|A_{k_{j+1}})}{P(A_{k_{j+1}}|A_{k_j})}P(Xi?=1?Ak1??Ak2??...Aks?)=P(Akj+1??Akj??)P(Akj??Xi?=1)P(Xi?=1Akj+1??)?

答案為 ∑i=1nP(Akj∣Xi=1)P(Xi=1∣Akj+1)P(Akj+1∣Akj)\sum_{i=1}^n\frac{P(A_{k_j}|X_i=1)P(X_i=1|A_{k_{j+1}})}{P(A_{k_{j+1}}|A_{k_j})}i=1n?P(Akj+1??Akj??)P(Akj??Xi?=1)P(Xi?=1Akj+1??)?

也就是說,已知結果將 nnn 局游戲劃分成了若干段區間,每段的貢獻計算的先決條件都是一樣的。

也就是說每個區間的答案為 ∑i=kj+1i=kj+1?1P(Akj∣Xi=1)P(Xi=1∣Akj+1)P(Akj+1∣Akj)\sum_{i=k_j+1}^{i=k_{j+1}-1}\frac{P(A_{k_j}|X_i=1)P(X_i=1|A_{k_{j+1}})}{P(A_{k_{j+1}}|A_{k_j})}i=kj?+1i=kj+1??1?P(Akj+1??Akj??)P(Akj??Xi?=1)P(Xi?=1Akj+1??)?

Q(r∣l):Q(r|l):Q(rl):lllRRR 贏的情況下,第 rrrRRR 贏的概率,~l\sim ll 則表示第 lllRRR 輸。

顯然有,Q(l+1∣l)=p[l+1]Q(l+1\Big|l)=p[l+1]Q(l+1?l)=p[l+1],再考慮計算 Q(l+2∣l)Q(l+2\Big|l)Q(l+2?l)
Q(l+2∣l)=Q(l+2∣l+1)?Q(l+1∣l)+Q(l+2∣~(l+1))?Q(~(l+1)∣l)=p[l+2]?p[l+1]+q[l+2]?(1?p[l+1])Q(l+2\Big|l)=Q(l+2\Big|l+1)·Q(l+1\Big|l)+Q(l+2\Big|\sim(l+1))·Q(\sim(l+1)\Big|l)\\=p[l+2]·p[l+1]+q[l+2]·(1-p[l+1]) Q(l+2?l)=Q(l+2?l+1)?Q(l+1?l)+Q(l+2?(l+1))?Q((l+1)?l)=p[l+2]?p[l+1]+q[l+2]?(1?p[l+1])
同理可計算出,Q(l+2∣~l),Q(~(l+2)∣l),Q(~(l+2)∣~l)Q(l+2\Big|\sim l),Q(\sim (l+2)\Big|l),Q(\sim (l+2)\Big|\sim l)Q(l+2?l),Q((l+2)?l),Q((l+2)?l)

發現,這其實是兩個矩陣相乘的結果,即 fl+1?fl+2f_{l+1}·f_{l+2}fl+1??fl+2?

fi=[1?qiqi1?pipi]f_{i}=\begin{bmatrix}1-q_i\quad\quad q_i\\1-p_i\quad\quad p_i\end{bmatrix}fi?=[1?qi?qi?1?pi?pi??]

可以繼續這么歸納下去,計算 Q(r∣l)Q(r\Big|l)Q(r?l) 等相關信息,無非就是一個連續區間的矩陣相乘后某個位置的結果。

∑i=kj+1i=kj+1?1P(Akj∣Xi=1)P(Xi=1∣Akj+1)P(Akj+1∣Akj)\sum_{i=k_j+1}^{i=k_{j+1}-1}\frac{P(A_{k_j}|X_i=1)P(X_i=1|A_{k_{j+1}})}{P(A_{k_{j+1}}|A_{k_j})}i=kj?+1i=kj+1??1?P(Akj+1??Akj??)P(Akj??Xi?=1)P(Xi?=1Akj+1??)?,用線段樹維護矩陣 fff

分母就是 fff 矩陣從 kjk_{j}kj? 一直乘到 kj+1k_{j+1}kj+1?

分子就是 fff 矩陣乘到 iii 位置時,只乘第二列(表示勝利),可以新定義一個矩陣 gig_igi?

gi=[0qi0pi]g_{i}=\begin{bmatrix}0\quad\quad q_i\\0\quad\quad p_i\end{bmatrix}gi?=[0qi?0pi??],在乘到 iii 位置時變成乘 gig_igi?

同樣用線段樹維護,gnow=flson?grson+glson?frson;fnow=flson?grsong_{now}=f_{lson}*g_{rson}+g_{lson}*f_{rson};f_{now}=f_{lson}*g_{rson}gnow?=flson??grson?+glson??frson?;fnow?=flson??grson?

最后就是具體實現問題了。

考慮插入兩個哨兵 0,n+10,n+10,n+1,初始局面答案就是一整個區間。

有涉及到詢問當前已知條件中的前驅 lll 后繼 rrr 問題,就需要用 STL 實現。

加點就用答案減去區間 (l,r)(l,r)(l,r) 的貢獻,再加上區間 (l,i)(l,i)(l,i) 和區間 (i,r)(i,r)(i,r) 的貢獻。

刪點就用答案減去區間 (l,i)(l,i)(l,i) 和區間 (i,r)(i,r)(i,r) 的貢獻,再加上區間 (l,r)(l,r)(l,r) 的貢獻。

code

#include <map> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; struct matrix {double c[2][2];// double * operator [] ( int x ) { return c[x]; }matrix() { memset( c, 0, sizeof( c ) ); }friend matrix operator + ( matrix u, matrix v ) {matrix ans;for( int i = 0;i < 2;i ++ )for( int j = 0;j < 2;j ++ )ans.c[i][j] = v.c[i][j] + u.c[i][j];return ans;}friend matrix operator * ( matrix u, matrix v ) {matrix ans;for( int i = 0;i < 2;i ++ )for( int j = 0;j < 2;j ++ )for( int k = 0;k < 2;k ++ )ans.c[i][j] += u.c[i][k] * v.c[k][j];return ans;}void print() {for( int i = 0; i < 2; i ++ ) {for( int j = 0; j < 2; j ++ )printf( "%.3f ", c[i][j] );printf( "\n" );}} }; #define maxn 200005 struct node { matrix f, g; }t[maxn << 2]; int n, m; char type; double ans; double p[maxn], q[maxn]; map < int, bool > x;#define lson now << 1 #define rson now << 1 | 1 #define mid ( ( l + r ) >> 1 )node operator + ( node x, node y ) {node ans;ans.f = x.f * y.f;ans.g = x.g * y.f + x.f * y.g;return ans; }void build( int now, int l, int r ) {if( l == r ) {t[now].f.c[0][0] = 1 - q[l];t[now].f.c[0][1] = t[now].g.c[0][1] = q[l];t[now].f.c[1][0] = 1 - p[l];t[now].f.c[1][1] = t[now].g.c[1][1] = p[l];// printf( "(%d):\n", l );// t[now].f.print();t[now].g.print();return;}build( lson, l, mid );build( rson, mid + 1, r );t[now] = t[lson] + t[rson];// printf( "{ %d } [%d, %d] ::\n", now, l, r );// t[now].f.print(); t[now].g.print(); }node query( int now, int l, int r, int L, int R ) {if( L <= l and r <= R ) return t[now];if( R <= mid ) return query( lson, l, mid, L, R );else if( mid < L ) return query( rson, mid + 1, r, L, R );else return query( lson, l, mid, L, R ) + query( rson, mid + 1, r, L, R ); }double Ask( int l, int r ) {node now = query( 1, 0, n + 1, l + 1, r );// now.f.print(); now.g.print();return now.g.c[x[l]][x[r]] / now.f.c[x[l]][x[r]]; }int main() {scanf( "%d %d %c %lf", &n, &m, &type, &p[1] );for( int i = 2;i <= n;i ++ ) scanf( "%lf %lf", &p[i], &q[i] );p[0] = q[0] = x[0] = 1, x[n + 1] = 0;build( 1, 0, n + 1 );ans = Ask( 0, n + 1 );// printf( "%f\n", ans );while( m -- ) {char opt[10]; int i, c;scanf( "%s", opt );if( opt[0] == 'a' ) {scanf( "%d %d", &i, &c );auto r = x.lower_bound( i );auto l = r;l --;x[i] = c;ans -= Ask( l -> first, r -> first );ans += Ask( l -> first, i );ans += Ask( i, r -> first );}else {scanf( "%d", &i );auto r = x.upper_bound( i );auto l = r;l --, l --;ans -= Ask( l -> first, i );ans -= Ask( i, r -> first );ans += Ask( l -> first, r -> first );x.erase( ++ l );}printf( "%f\n", ans );}return 0; }

總結

以上是生活随笔為你收集整理的[UOJ299][CTSC2017] 游戏的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。