吐槽一句:这数据造得真强….

题意:有一个大小为k的缓存区,每次从n种物品中按照一定的概率选取一种物品尝试放进去.同一个物品每一次选取的概率都是相同的.如果这种物品已经放进去过就不再放进去.如果缓存区满了就把放进去的时间离现在最远的物品拿出来.问10^100次后每个物品在缓冲区中的概率.

如果正着做的话似乎状态会扩展得很多而且都没什么用.

注意到最后一次放进去的一个物品肯定在缓冲区中,而第一次放进去的物品对结果几乎没有影响,这提示我们关注最后的几次放置.假如缓冲区至少有两个位置,且倒数第二个物品和倒数第一个物品种类不同,那么倒数第二个物品也肯定在缓冲区中.

因此最终缓冲区中存放着我们所放进去的倒数几个物品.那么我们在物品的选取序列中从最后倒着往前扫,数出前k种不同的物品,就是缓冲区中最后存放的k种物品.而选取序列中,每个位置都按照给定的概率出现n种物品.

因此我们可以令F[i][S]表示缓冲区已经拥有了i种物品时拥有的物品集合为S的情况发生的概率.那么枚举所有不在S中的物品.如果所有不在S中的物品的概率之和为P,某种不在S中的物品x被选中的概率为pi,那么拿到的下一种不在S中的物品是x的概率为pi/P(在这之前可能拿了不止一次,也可能拿到过属于S的物品).可以预处理一下被选中的物品属于某个集合的概率以及属于某个集合的物品个数.

提醒一下,这道题的最后一个数据点简直了….我在程序中只使用了集合中包含元素个数=k的状态更新答案,因为我假定无穷次放置之后每个物品至少会拿到一次,又因为k<=n,所以最终缓存区一定是满的.但这个推理不成立,因为” 无穷次放置之后每个物品至少会拿到一次”这个前提是错的.物品被拿到的概率区间是[0,1]闭区间,虽然保证了k<=n,但并没有保证选中概率不为0的物品个数大于等于k,所以可能放不满k个位置,这时选中概率不为0的物品出现概率都是1.对于这种情况,我们需要特判一下.(后来想了想,此时可以直接输出答案,不需要跑DP,又sb了一次)

调的时候我想到k>n的时候不能只考虑集合元素个数为k的情况,但看到数据保证k<=n就没处理.想到了概率可以为0,但只是做了防止除0的处理,并没有想到缓存区可以放不满...思维还是不够缜密啊.

Codeforces评论区里貌似还有两种神做法...一会儿搞一搞 http://codeforces.com/blog/entry/46148

#include<cstdio>
long double f[1<<20];
double p[1<<20];
int g[1<<20];
double ans[20];
int main(){f[0]=1;int n,k;scanf("%d%d",&n,&k);int cnt=n;for(int i=0;i<n;++i){scanf("%lf",&p[1<<i]);if(p[1<<i]==0)cnt--;//如果概率为0的物品太多,可能放不满k个
  }if(cnt<k)k=cnt;int lim=1<<n;for(int i=1;i<lim;++i){p[i]=p[i&(-i)]+p[i^(i&(-i))];//printf("%f\n",p[i]);g[i]=(i&1)+g[i>>1];}//  printf("%f\n",p[lim-1]);for(int i=0;i<lim;++i){//printf("%f\n",f[i]);for(int j=0;j<n;++j){if(i&(1<<j))continue;if(p[i]!=1)f[i^(1<<j)]+=f[i]*p[1<<j]/(1-p[i]);//防止除零
    }if(g[i]==k){for(int j=0;j<n;++j){if(i&(1<<j))ans[j]+=f[i];}}}for(int i=0;i<n;++i)printf("%.7f%c",ans[i],(i==n-1)?'\n':' ');return 0;
}

来更新啦

好像其中一个人只是讲了他在打比赛的时候推着推着推回去了的故事…(不要问我是怎么把这看成一个做法的…我英语拙计…)

另一个做法是容斥(别人的高科技代码传送门http://codeforces.com/contest/699/submission/19261510 ).

分别考虑每个物品i.假如这个物品i最后一次出现后,又出现了j个其他物品(j=0,1,2,3,….inf),如果这个物品最后出现了,那么这j个其他物品中最多只能含有k-1种物品.考虑一个含有k-1种物品的集合,假如这个集合中所有物品的概率之和为x,那么上面这些情况发生的概率分别为ai,ai*x,ai*x^2,…..ai*x^inf,概率之和P=ai/(1-x){从P=ai+x*P推出}.如果我们枚举所有含有k-1个物品的集合,把它们的P加起来,将导致大量重复.含有k-2,k-3…个物品的情况都被重复计数.因此我们枚举k-2个物品的集合,每个k-2个物品的集合在每个包含它的k-1个物品的集合中被加上了一次.接下来每个k-3个物品的集合在k-2个物品的集合中被加上,在k-1个物品的集合中被减去…这个容斥的系数可以预处理出来(突然发现自己并不会容斥……)

别人的题解:

#include<cstdio>
double a[20];
double p[1<<20];
int g[1<<20];
double C[21][21];
double h[21];
int main(){int n,k;scanf("%d%d",&n,&k);for(int i=0;i<n;++i){scanf("%lf",a+i);}int lim=(1<<n)-1;for(int i=0;i<n;++i){p[1<<i]=a[i];}for(int i=1;i<lim;++i){p[i]=p[i&(-i)]+p[i^(i&(-i))];g[i]=(i&1)+g[i>>1];}C[0][0]=1;for(int i=1;i<=20;++i)C[i][0]=1;for(int i=1;i<=20;++i){for(int j=1;j<=i;++j){C[i][j]=C[i-1][j]+C[i-1][j-1];}}for(int i=k-1;i>=0;--i){h[i]=1;for(int j=i+1;j<=k-1;++j){h[i]-=h[j]*C[(n-1)-i][j-i];}}// for(int i=0;i<=k-1;++i)printf("%d %f\n",i,h[i]); double ans=0;for(int i=0;i<n;++i){if(a[i]==0||a[i]==1||k==1){printf("%.7f%c",a[i],(i==n-1)?'\n':' ');continue;}ans=0;for(int j=0;j<lim;++j){if((g[j]<k)&&(!(j&(1<<i)))){//    printf("%f\n",H[g[j]]);ans+=h[g[j]]/(1-p[j]);}}printf("%.7f%c",a[i]*ans,(i==n-1)?'\n':' ');}return 0;
}

转载于:https://www.cnblogs.com/liu-runda/p/6256730.html

CodeForces 698C LRU相关推荐

  1. linux使分区生效,Linux 硬盘分区生效命令partprobe

    在Linux中使用fdisk命令进行分区时,有时会遇到"WARNING: Re-reading the partition table failed with error 16: Devic ...

  2. codeforces泛做

    codeforces div1的题目,一般是做B.C.D 有的A题觉得有价值也会做,死活不会的就跳了-- 364 B: Connecting Universities Problem: 一颗无根树上给 ...

  3. CodeForces 375D Tree and Queries

    传送门:https://codeforces.com/problemset/problem/375/D 题意: 给你一颗有根树,树上每个节点都有其对应的颜色,有m次询问,每次问你以点v为父节点的子树内 ...

  4. 「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)

    题意与分析(CodeForces 540D) 是一道概率dp题. 不过我没把它当dp做... 我就是凭着概率的直觉写的,还好这题不算难. 这题的重点在于考虑概率:他们喜相逢的概率是多少?考虑超几何分布 ...

  5. 【codeforces 812C】Sagheer and Nubian Market

    [题目链接]:http://codeforces.com/contest/812/problem/C [题意] 给你n个物品; 你可以选购k个物品;则 每个物品有一个基础价值; 然后还有一个附加价值; ...

  6. CodeForces 获得数据

    针对程序的输出可以看见 CodeForces :当输入.输出超过一定字符,会隐藏内容 所以:分若干个程序进行输入数据的获取 1. 1 for (i=1;i<=q;i++) 2 { 3 scanf ...

  7. codeforces水题100道 第二十七题 Codeforces Round #172 (Div. 2) A. Word Capitalization (strings)...

    题目链接:http://www.codeforces.com/problemset/problem/281/A 题意:将一个英文字母的首字母变成大写,然后输出. C++代码: #include < ...

  8. CodeForces 595A

    题目链接: http://codeforces.com/problemset/problem/595/A 题意: 一栋楼,有n层,每层有m户,每户有2个窗户,问这栋楼还有多少户没有睡觉(只要一个窗户灯 ...

  9. codeforces A. Jeff and Digits 解题报告

    题目链接:http://codeforces.com/problemset/problem/352/A 题目意思:给定一个只有0或5组成的序列,你要重新编排这个序列(当然你可以不取尽这些数字),使得这 ...

最新文章

  1. web中的cookies以及作用--web testing 学习笔记
  2. gitlab常用命令
  3. 刘强东:第四次零售革命意义将超互联网
  4. JAVA设计模式之单例设计模式
  5. Modbus协议栈开发笔记之五:Modbus RTU Slave开发
  6. html树形结构主从命名,HAP_头⾏/主从结构的实现
  7. mysql statistics cpu_(2条消息) Mysql占用CPU过高如何优化,如何解决
  8. tornadod的异步代码
  9. 炒菜多放油:确实好吃,可是又不健康
  10. 【优化调度】基于matlab粒子群算法求解水电厂优化调度购电最小问题【含Matlab源码 1234期】
  11. iOS不能显示英文音标问题
  12. 计算机无法删除u盘里东西,u盘里东西删不掉,详细教您u盘文件删不了怎么办
  13. 2022中国大学python语言程序设计测试六答案(北理工嵩天 、黄天羽 、礼欣)
  14. 古籍、中国通史、诗经、辞、、四书五经、诸子百家、四大名著、唐诗、宋词、明清小说、四库全书
  15. Json字符串的转换
  16. 12V不间断电源模块,智能直流UPS的设计需求-应用于工业电脑异常断电
  17. 教你PDF复制文字的方法
  18. H.265与H.264的区别详解
  19. linux学习课程从入门到精通:文件的归档和压缩
  20. android 9.0 添加自定义恢复出厂设置标识

热门文章

  1. 图标(ico,cur)文件的结构解析
  2. 【Cocos2D-x 3.5实战】坦克大战(1)环境配置
  3. arduino uno+驱动器控制42步进电机
  4. Google基本查询语法
  5. 高精度地图:自动驾驶的向导
  6. 【电容】关于电容,这篇说得太详细了
  7. uc打开html文件是空的,UC浏览器中打开不出现主页的解决方法
  8. SAP ITS Mobile
  9. 一个存储过程帮你了解 事务(TRAN)、异常处理(TRY/CATCH)、@@ERROR
  10. Booting ARM Linux