• CF698C LRU


    CF698C LRU

    题目大意

    题目链接

    有一个初始为空的队列,容量为 (k)。有 (n) 种物品。

    接下来会进行 (10^{100}) 次操作。每次选择一个物品,物品 (i)(p_i) 的概率被选中。如果被选中的物品不在队列中,则将它加入队列。此时如果队列长度大于 (k),则弹出“上一次被选中的时间”最早的物品。

    问所有操作结束后,每个物品仍在队列中的概率。保留 (6) 位小数。

    数据范围:(1leq kleq nleq 20)(0leq p_ileq 1)(sum p_i = 1)

    本题题解

    考虑对每个物品分别求答案。那么有两种情况:

    1. 操作结束时,队列内不到 (k) 种物品。
    2. 操作结束时,队列内有 (k) 种物品(是满的)。

    如果 (p_i eq 0) 的物品数 (< k),显然只能是情况 1。因为操作次数极大,而且不发生弹出,所以所有 (p_i eq 0) 的物品答案都是 (1)

    否则,在经过了 (10^{100}) 次操作后,情况 1 出现的概率可以近似视为 (0)。故以下只考虑情况 2。

    考虑最终的队列里有哪些物品。发现就是最后加入的 (k) 物品。例如,(k = 3),若操作序列(每次选择的物品)为:(dots ,2,2,1,5,1,3,3,4),则最终队列里就是:({1,3,4})

    考虑状压 DP。设 ( ext{dp}(s)) 表示操作序列的一个后缀里,物品集合为 (s) 的概率。(s) 是一个二进制状压。

    转移时,枚举下一个还未在 (s) 内出现过的物品,记为物品 (u)(其实是操作序列更前面的物品,因为根据状态设计,我们是从后往前 DP 的)。设 ( ext{sum}(s) = sum_{vin s}p_v)。则:

    [forall u otin s, p_u eq 0: quad ext{dp}(s)cdot (p_u + ext{sum}(s)cdot p_u + ext{sum}(s)^2cdot p_u + dots) o ext{dp}(s cup {u}) ]

    括号里的式子,表示:【下一次就选中 (u) 的概率】 (+) 【先选中一个已有的数,再下次才选中 (u) 的概率】 (+) 【下下下次才选中 (u) 的概率】 (dots)。因为操作次数极大,所以有:

    [egin{align} & ext{dp}(s) cdot sum_{i = 0}^{infty} ext{sum}(s)^i cdot p_u\ =& ext{dp}(s)cdot p_ucdot sum_{i = 0}^{infty} ext{sum}(s)^i\ =& ext{dp}(s)cdot p_ucdot frac{1}{1 - ext{sum}(s)} end{align} ]

    也可以这样理解上述的转移式:只要选到 (s) 里的数,我们就假装无事发生,再选一次。浪费的这一次操作对答案没有影响,因为总操作次数近似无穷大。所以这就等价于,我们强行把 (s) 集合里已有的数,被抽到的概率视为 (0)。剩下的数概率对应地变为:(displaystyle p_u' = frac{p_u}{sum_{v otin s}p_v} = frac{p_u}{1 - ext{sum}(s)})

    于是就可以转移了。

    边界是:( ext{dp}(0) = 1)。物品 (i) 的答案就是 (displaystyle sum_{iin s, |s| = k} ext{dp}(s))

    时间复杂度 (mathcal{O}(2^nn))

    参考代码

    // problem: CF698C
    #include <bits/stdc++.h>
    using namespace std;
    
    #define mk make_pair
    #define fi first
    #define se second
    #define SZ(x) ((int)(x).size())
    
    typedef unsigned int uint;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int, int> pii;
    
    template<typename T> inline void ckmax(T& x, T y) { x = (y > x ? y : x); }
    template<typename T> inline void ckmin(T& x, T y) { x = (y < x ? y : x); }
    
    const int MAXN = 20;
    
    int n, K;
    int hibit[1 << MAXN], bitcnt[1 << MAXN];
    double p[MAXN + 5], sum[1 << MAXN];
    double f[1 << MAXN];
    
    int main() {
    	cin >> n >> K;
    	int cnt = 0;
    	for (int i = 1; i <= n; ++i) {
    		cin >> p[i];
    		cnt += (p[i] != 0);
    	}
    	if (cnt < K) {
    		for (int i = 1; i <= n; ++i) {
    			cout << (p[i] == 0 ? 0 : 1) << ".00000000" << " 
    "[i == n];
    		}
    		return 0;
    	}
    	
    	for (int i = 1; i <= n; ++i) {
    		hibit[1 << (i - 1)] = i;
    	}
    	for (int i = 1; i < (1 << n); ++i) {
    		bitcnt[i] = bitcnt[i - (i & (-i))] + 1;
    		sum[i] = sum[i - (i & (-i))] + p[hibit[i & (-i)]];
    	}
    	
    	f[0] = 1;
    	for (int i = 1; i < (1 << n); ++i) {
    		if (bitcnt[i] > K)
    			continue;
    		for (int _j = i; _j; _j -= (_j & (-_j))) {
    			int j = hibit[_j & (-_j)];
    			
    			assert((1 << (j - 1)) == (_j & (-_j)));
    			
    			if (p[j] == 0)
    				continue;
    			
    			f[i] += f[i ^ (1 << (j - 1))] * (p[j] / sum[((1 << n) - 1) ^ i ^ (1 << (j - 1))]);
    		}
    	}
    	cout << setiosflags(ios :: fixed) << setprecision(10);
    	
    	for (int i = 1; i <= n; ++i) {
    		/*
    		double ans = pow(1.0 - p[i], 100000000); // 没出现过 
    		for (int s = 0; s < (1 << n); ++s) {
    			if (((s >> (i - 1)) & 1) == 0 && bitcnt[s] >= K) {
    				ans += p[i] / sum[((1 << n) - 1) ^ s] * f[s]; // 出现了但被代替 
    			}
    		}
    		ans = 1.0 - ans;
    		cout << ans << " 
    "[i == n];
    		*/
    		
    		double ans = 0;
    		for (int s = 0; s < (1 << n); ++s) {
    			if (((s >> (i - 1)) & 1) && bitcnt[s] == K) {
    				ans += f[s];
    			}
    		}
    		cout << ans << " 
    "[i == n];
    	}
    	return 0;
    }
    
  • 相关阅读:
    Android 常用开发类库
    Java 8 时间日期库的20个使用演示样例
    数据格式转换 (三)Office文档转HTML
    2011年读过的书及2012年即将要读的书
    nodeJs学习路线
    Android入门篇(一)Androidproject的搭建,导入与导出,图标的改动
    MySQL 使用自增ID主键和UUID 作为主键的优劣比較具体过程(从百万到千万表记录測试)
    实战Jquery(四)--标签页效果
    Xcode加入应用图标以及启动界面
    poj 2240 Bellman-Flod 求环
  • 原文地址:https://www.cnblogs.com/dysyn1314/p/14297318.html
Copyright © 2020-2023  润新知