Codeforces Round #363 (Div. 1) C LRU

来源:互联网 发布:java c base64 通用 编辑:程序博客网 时间:2024/06/03 00:43

C. LRU

  按最近最少使用原则,维护n首歌曲的缓存,缓存容量为k,只有最近出现过的k首歌会出现在缓存内。每首歌有一定的被选择的概率,问很长时间以后每首歌出现在缓存中的概率。
  倒过来考虑,问题等价于不断按给定概率选取歌曲,直到选取了k首为止,问每首歌被选择的概率。
  用一个20位的二进制数来表示歌曲的集合,dp求每个集合可取得的概率,具体见代码。

#include <bits/stdc++.h> using namespace std;#define ll long longdouble dp[1<<20]; double p[22];double ans[22];int bit_cnt[1<<20]; int main(){    int n,k;    cin>>n>>k;    for(int i=0;i<n;i++){        cin>>p[i];    }    int End = 1<<(n);    for(int i=1;i<End;i++){        //注意这个内置位运算函数         bit_cnt[i] = __builtin_popcount(i);    }    dp[0] = 1;    for(int j=1;j<End;j++){        dp[j] = 0;        double pp = 0;        for(int kk=0;kk<n;kk++){            if(j&(1<<kk)){                dp[j] += dp[j^(1<<kk)] * p[kk];                pp += p[kk];            }        }        //当前的dp[j]是第一次获得该集合的概率,答案需要的就是“第一次得到”的概率        if(bit_cnt[j] == k ){            for(int i=0;i<n;i++){                if(j&(1<<i)){                    ans[i] += dp[j];                }            }        }        //根据等比数列求和公式,得到(在很长一段时间内)维持该集合的概率         dp[j] /= (1-pp);    }    int cnt = n;    for(int i=0;i<n;i++){        if(p[i] == 0){            cnt--;        }    }    if(cnt<k){        for(int i=0;i<n;i++){            printf("%.8f ", (p[i]==0.0)?0.0:1.0);        }    }else{        for(int i=0;i<n;i++){            printf("%.8f ",ans[i]);        }    }    return 0;}
0 0
原创粉丝点击