zoukankan      html  css  js  c++  java
  • 序列合并

    Problem

    有一个序列,初始时为空,你会不断往序列末尾添加一个 ([1, m]) 的随机整数。

    任意时刻

    • 若序列末尾两个数相同(记为 (x)),且小于 (t),则这两个数会合并成 (x+1)

    • 若序列长度为 (n) 且无法合并,则操作结束。

    求序列中所有元素和的期望,答案对 (10^9+7) 取模。

    (1leq n,mleq 10^3)(mleq tleq 10^9)

    Solution

    (L=min{t, n+m-1})

    (p_{i,j}):限制序列长度为 (i),第一个位置出现 (j) 的概率。

    [p_{i,j}=[jleq m]frac1m+p_{i,j-1} imes p_{i-1,j-1} ]

    (q_{i,j}):限制序列长度为 (i),第一个位置为 (j) 下,之后不再改变的概率。

    [q_{i,j}=1-[j<L]p_{i-1,j} ]

    (g_{i,j}):限制序列长度为 (i),第一个位置为 (j),且之后不再改变后,整个序列的期望。

    (ans_i):序列长度为 (i) 时,权值和的期望。

    (f_{i,j}):序列长度为 (i),第一个数字出现 (j) 时,序列元素权值和。

    (j<L) 时,

    [egin{aligned} g_{i,j}&=j+sum_{S}S imesPr{第2到i权值和为S|第1个为j,且j不变}\ &=j+frac{sum_{S}S imesPr{第2到i权值和为S,j不改变|第1个为j}}{Pr{j不改变|第1个为j}}\ &=j+frac{sum_{S}S imesPr{第2到i权值和为S,j不改变|第1个为j}}{q_{i,j}}\ &=j+frac{sum_{S}S imesPr{第2到i权值和为S,j任意|第1个为j}-sum_{S}S imesPr{第2到i权值和为S,j改变|第1个为j}}{q_{i,j}}\ &=j+frac{ans_{i-1}-Pr{第2个为j} imessum_S S imesPr{第2到i权值和为S|第2个为j}}{q_{i,j}}\ &=j+frac{ans_{i-1}-p_{i-1,j} imes f_{i-1,j}}{q_{i,j}} end{aligned} ]

    (j=L) 时,

    [g_{i,j}=j+ans_{i-1} ]

    对于 (ans_i)

    [ans_i=sum_{j=1}^Lp_{i,j} imes q_{i,j} imes g_{i,j} ]

    对于 (f_{i,j})

    [f_{i,j}=q_{i,j} imes g_{i,j}+(1-q_{i,j}) imes f_{i,j+1} ]

    为了避免求逆元,将 (g_{i,j} imes q_{i,j}) 整体转移。复杂度 (mathcal O(nm))

    Code

    #include <bits/stdc++.h>
    const int N = 2005, P = 1e9 + 7;
    using std::min;
    int n, m, t, L, f[N][N], qg[N][N], p[N][N], q[N][N], ans[N];
    int qpow(int a, int b) {
    	int t = 1;
    	for (; b; b >>= 1, a = 1LL * a * a % P)
    		if (b & 1) t = 1LL * t * a % P;
    	return t;
    }
    int main() {
    	scanf("%d%d%d", &n, &m, &t); L = min(n + m - 1, t);
    	int inv = qpow(m, P-2);
    	for (int i = 1; i <= n; i++) {
    		for (int j = 1; j <= L; j++) {
    			p[i][j] = ((j <= m ? inv : 0) + 1LL * p[i][j - 1] * p[i - 1][j - 1]) % P;
    			q[i][j] = (1 - (j < L ? p[i - 1][j] : 0) + P) % P;
    		}
    		for (int j = L; j; j--) {
    			qg[i][j] = (1LL * q[i][j] * j + ans[i - 1] - (j < L ? 1LL * p[i - 1][j] * f[i - 1][j] % P : 0) + P) % P;
    			f[i][j] = (qg[i][j] + (j < L ? 1LL * (1 - q[i][j] + P) * f[i][j + 1] : 0)) % P;
    			ans[i] = (ans[i] + 1LL * p[i][j] * qg[i][j]) % P;
    		}
    	}
    	printf("%d
    ", ans[n]);
    	return 0;
    }
    
  • 相关阅读:
    python--模块与包
    内置函数 的总结
    迭代器 生成器 列表推导式 生成器表达式的一些总结
    函数的有用信息 带参数的装饰器 多个装饰器装饰一个函数
    函数名的应用(第一对象) 闭包 装饰器
    动态参数 名称空间 作用域 作用域链 加载顺序 函数的嵌套 global nonlocal 等的用法总结
    函数的初识 函数的返回值 参数
    文件操作 常用操作方法 文件的修改
    遍历字典的集中方法 集合的作用 以及增删查的方法
    计算机硬件的小知识
  • 原文地址:https://www.cnblogs.com/ac-evil/p/14433082.html
Copyright © 2011-2022 走看看