●CodeForces 698C LRU
题链:
http://codeforces.com/problemset/problem/698/C
题解.1:
概率dp,状压dp
棒棒哒题解:https://www.cnblogs.com/liu-runda/p/6256730.html
由于操作次数很多,所以可以看成无穷次,
且题中明确给出K<=N,所以一般来说最后的缓存区中有k个物品的概率非常接近1。
或者这么来理解:
如果这么多次的操作我们都只取到了某固定的k-1个物品,那么也就意味这其它的物品一次都没取到过,
设其它物品的概率和为x,那么它们一次都没取到的概率就为x^inf,非常接近0,即基本不可能只取到过某固定的k-1个物品。
(当然也有特殊情况,如果某些物品(假设有h个)的出现概率为0,那么只有N-h个物品可能被得到,
所以K=min(k,N-h),更改一下缓存区里能存在的物品的最大个数)
显然,对于任意一个操作序列,操作结束后,缓冲区里存在哪k个物品,只与这个操作序列的末尾有关。
更详细的是指:那k个物品,就是这个操作序列从后往前数,首先数到的k个不同的物品。(然后前面的物品无论怎样出现都没有任何关系了)
那么只要求得一个k个物品的集合的出现概率P,那么这个集合里面所有元素的出现概率都要+P。
然后我们需要计算出所有k个物品的集合的出现概率,而且k的大小是20,毫不犹豫的想到状压dp
令dp[S]表示从后往前已经拥有的物品的集合为S的出现概率:
设S集合里的物品出现的概率和为x,然后枚举每个不在S里的物品i。
dp[S|idx(i)]=dp[S]*p[i]/(1-x).
p[i]/(1-x)意思是i物品在未出现的物品种出现的概率。
因为遇到已在S里的物品对S这个状态没有任何影响,所以只考虑不在S里的物品。
然后每当S的大小为K时,就把dp[S]加到S里的每个物品i的出现概率ans[i]上去。
代码.1:
#include<bits/stdc++.h>
#define MAXN 20
using namespace std;
const double eps=1e-9;
double p[1<<MAXN],g[1<<MAXN],ans[MAXN+5],dp[1<<MAXN];
int cnt[1<<MAXN];
int N,K,ALL,k;
int idx(int i){return 1<<(i-1);}
int dcmp(double x){
if(fabs(x)<eps) return 0;
return x>0?1:-1;
}
int main(){
ios::sync_with_stdio(0);
cin>>N>>K; ALL=idx(N+1); k=N;
for(int i=1;i<=N;i++){
cin>>p[idx(i)];
if(dcmp(p[idx(i)])==0) k--;
}
K=min(k,K);
for(int S=1,i;i=S&(-S),S<ALL;S++)
g[S]=g[S^i]+p[i],cnt[S]=cnt[S^i]+1;
dp[0]=1;
for(int S=1;S<ALL;S++){
for(int i=1;i<=N;i++) if(idx(i)&S)
if(dcmp(1-g[idx(i)^S])!=0) dp[S]+=dp[S^idx(i)]*p[idx(i)]/(1-g[S^idx(i)]);
if(cnt[S]==K) for(int i=1;i<=N;i++) if(idx(i)&S) ans[i]+=dp[S];
}
for(int i=1;i<=N;i++)
cout<<fixed<<setprecision(7)<<ans[i]<<" ";
return 0;
}
题解.2:
容斥,概率
同样的,由于操作次数为10^100,所以可以看成是无穷次。
假设对于一个操作序列,如果要使得最后的k个物品中存在i物品,
那必然在最后一次出现了i物品之后出现的其他物品种类数不超过k-1种.(即可能出现了0种其它物品,1种其它物品,2种其他物品,...,k-1种其他物品)
现在我们假设之后出现了k-1种其它物品,这k-1种物品的集合为S,且这k-1种物品的出现概率和为x,
那么由于i物品最后一次出现的具体位置未知,
所以有如下计算式来计算上述这种“出现了i以后再出现的其他物品种类不超过k-1种且集合为S”的情况的发生概率:
P=p[i]*(x+x^2+x^3+...+x^inf)=p[i]*1.0/(1-x)
由于这只是一种k-1种物品的集合的情况,所以还要枚举所有的k-1种物品的集合来进行上述操作,并把每个求得的概率累加到一起。
显然,存在了许多重复和无用信息,
举个例子,上面由若干个k-1种物品的集合所得到的概率和∑P中,
把任意一种“出现了i以后再出现的其他物品种类不超过k-2种且集合为S'”的情况的都包含了若干次,
具体来说是C(N-1-(k-2),1)次,(也就是S'的不含i物品的超集的个数)
所以需要把这些多余的减去,这就是容斥的原因,
注意到容斥系数只与集合大小有关,
我们只需要预处理出集合大小为cnt时的容斥系数即可。
(因为我们要求之后出现的其他物品种类为0种,1种,2种...k-1的概率和,所以在处理容斥系数之前,首先把每个的容斥系数都定为1)
代码.2:
#include<bits/stdc++.h>
#define MAXN 20
using namespace std;
const double eps=1e-9;
double a[MAXN],p[1<<MAXN],h[MAXN+5],dp[1<<MAXN],c[MAXN+5][MAXN+5];
int cnt[1<<MAXN];
int N,K,ALL,k;
int idx(int i){return 1<<(i-1);}
int dcmp(double x){
if(fabs(x)<eps) return 0;
return x>0?1:-1;
}
int main(){
ios::sync_with_stdio(0);
cin>>N>>K; ALL=1<<N;
for(int i=1;i<=N;i++) cin>>a[i],p[idx(i)]=a[i];
for(int S=1,i;i=S&(-S),S<ALL;S++)
p[S]=p[i]+p[S^i],cnt[S]=1+cnt[S^i];
for(int i=0;c[i][0]=1,i<=N;i++)
for(int j=1;j<=i;j++)
c[i][j]=c[i-1][j-1]+c[i-1][j];
for(int i=K-1;h[i]=1,i>=0;i--)
for(int j=i+1;j<=K-1;j++)
h[i]-=h[j]*c[N-1-i][j-i];
cout<<fixed<<setprecision(7);
for(int i=1;i<=N;i++){
if(dcmp(a[i])==0||dcmp(1-a[i])==0||K==1)
cout<<p[idx(i)];
else{
double ans=0;
for(int S=0;S<ALL;S++){
if(idx(i)&S||cnt[S]>=K) continue;
ans+=h[cnt[S]]*1.0/(1-p[S]);
}
cout<<ans*p[idx(i)];
}
cout<<((i==N)?'\n':' ');
}
return 0;
}
●CodeForces 698C LRU的更多相关文章
- CodeForces 698C LRU
吐槽一句:这数据造得真强-. 题意:有一个大小为k的缓存区,每次从n种物品中按照一定的概率选取一种物品尝试放进去.同一个物品每一次选取的概率都是相同的.如果这种物品已经放进去过就不再放进去.如果缓存区 ...
- 【codeforces 698C】LRU
题目链接: http://codeforces.com/problemset/problem/698/C 题目大意: n个物品,k个格子,第i个物品每次被选取的概率为$p_{i}$,如果格子里没有该物 ...
- 【CodeForces】698 C. LRU
[题目]C. LRU [题意]给定空间为k的背包和n个物品,每次每个物品有pi的概率加入(Σpi=1),加入时若发现背包中已有该物品则不改变,若背包满k个物品后再加入新物品则弹出最早加入的物品,求加入 ...
- Codeforces Round #363 (Div. 2)E. LRU
E. LRU time limit per test 2 seconds memory limit per test 256 megabytes input standard input output ...
- Codeforces Round #363 LRU(概率 状压DP)
状压DP: 先不考虑数量k, dp[i]表示状态为i的概率,状态转移方程为dp[i | (1 << j)] += dp[i],最后考虑k, 状态表示中1的数量为k的表示可行解. #incl ...
- Codeforces Round #363 (Div. 1) C. LRU
题意: n个数,长度为k的缓存,每次询问,每个数以pi的概率被选,如果不在缓存区则加入,如果缓存区满了,则第一个进缓存的出来,问10^100次询问以后每个数在缓存的概率 思路: 状压DP,看了hzwe ...
- codeforces泛做..
前面说点什么.. 为了完成日常积累,傻逼呵呵的我决定来一发codeforces 挑水题 泛做.. 嗯对,就是泛做.. 主要就是把codeforces Div.1的ABCD都尝试一下吧0.0.. 挖坑0 ...
- Codeforces Round 363 Div. 1 (A,B,C,D,E,F)
Codeforces Round 363 Div. 1 题目链接:## 点击打开链接 A. Vacations (1s, 256MB) 题目大意:给定连续 \(n\) 天,每天为如下四种状态之一: 不 ...
- 【cf比赛记录】Codeforces Round #605 (Div. 3)
比赛传送门 Div3真的是暴力杯,比div2还暴力吧(这不是明摆的嘛),所以对我这种一根筋的挺麻烦的,比如A题就自己没转过头来浪费了很久,后来才醒悟过来了.然后这次竟然还上分了...... A题:爆搜 ...
随机推荐
- C语言程序设计(基础)- 第4周作业
一.PTA作业 完成PTA第四周作业中8个题目,并将其中4个题目的思路列在博客中. 1.7-1 计算分段函数[1] 2.7-2 A除以B 3.7-6 阶梯电价 4.7-7 出租车计价 随笔具体书写内容 ...
- 冲刺NO.10
Alpha冲刺第十天 站立式会议 项目进展 项目核心功能逐步构建完成,测试工作也已开始.主要对部分功能组合进行测试以测试系统可用性. 问题困难 项目的主要困难在这个时间点主要存在于测试工作中,测试工作 ...
- bzoj千题计划214:bzoj3589: 动态树
http://www.lydsy.com/JudgeOnline/problem.php?id=3589 树链剖分 用线段数维护扫描线的方式来写,标记只打不下传 #include<cstdio& ...
- Mysql必须知道的知识
最近在准备面试,所以也整理了一些Mysql数据库常用的知识,供大家参考. 1.MySQL的复制原理以及流程 (1).复制基本原理流程 1. 主:binlog线程--记录下所有改变了数据库数据的语句,放 ...
- ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'name' not found. Available parameters are [arg1, arg0, param1, param2]
org.apache.ibatis.exceptions.PersistenceException: ### Error updating database. Cause: org.apache.ib ...
- mySql一个字段的值模糊匹配多表多列的查询
1.dao层/** * 分页查询点卡集合信息 * @param tid 游戏类型编号 * @param gid 游戏编号 * @param searchInfo 包括(点卡名称,游戏名称,点卡面值,游 ...
- Docker学习笔记 - Docker的数据卷
一.什么是数据卷? 数据卷是一个可供一个或多个容器使用的特殊目录,它绕过 UFS,可以提供很多有用的特性: 数据卷可以在容器之间共享和重用 对数据卷的修改会立马生效 对数据卷的更新,不会影响镜像 数据 ...
- Spring Security 入门(1-5)Spring Security - 匿名认证
匿名认证 对于匿名访问的用户,Spring Security 支持为其建立一个匿名的 AnonymousAuthenticationToken 存放在 SecurityContextHolder 中, ...
- OAuth2.0学习(1-7)授权方式4-客户端模式(Client Credentials Grant)
授权方式4-客户端模式(Client Credentials Grant) 客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提 ...
- Python之函数的进阶(带参数的装饰器)
函数篇--装饰器二 带参数的装饰器 def outer(flag): def timer(func): def inner(*args,**kwargs): if flag: print('''执行函 ...