n个数,长度为k的缓存,每次询问,每个数以pi的概率被选,如果不在缓存区则加入,如果缓存区满了,则第一个进缓存的出来,问10^100次询问以后每个数在缓存的概率
思路:
状压DP,看了hzwer的代码
f[x]表示当前状态为x的概率
枚举不在缓存区的数:f[t]+=f[x]*(p[i]/tot); t=x|(1<<(i-1)); tot是当前状态情况下,不在缓存区的所有概率
如果缓存区数大于k,则当前状态概率为0
1 // #pragma comment(linker, "/STACK:102c000000,102c000000") 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <sstream> 6 #include <string> 7 #include <algorithm> 8 #include <list> 9 #include <map> 10 #include <vector> 11 #include <queue> 12 #include <stack> 13 #include <cmath> 14 #include <cstdlib> 15 // #include <conio.h> 16 using namespace std; 17 #define clc(a,b) memset(a,b,sizeof(a)) 18 #define inf 0x3f3f3f3f 19 #define lson l,mid,rt<<1 20 #define rson mid+1,r,rt<<1|1 21 const int N = 2e5+10; 22 const int M = 1e6+10; 23 const int MOD = 1e9+7; 24 #define LL long long 25 #define LB long double 26 #define mi() (l+r)>>1 27 double const pi = acos(-1); 28 const double eps = 1e-8; 29 void fre() { 30 freopen("in.txt","r",stdin); 31 } 32 // inline int r() { 33 // int x=0,f=1;char ch=getchar(); 34 // while(ch>‘9‘||ch<‘0‘) {if(ch==‘-‘) f=-1;ch=getchar();} 35 // while(ch>=‘0‘&&ch<=‘9‘) { x=x*10+ch-‘0‘;ch=getchar();}return x*f; 36 // } 37 int n,k; 38 LB p[25],ans[25],f[1<<21]; 39 LB dp(int x){ 40 if(x==0) f[x]=1; 41 LB tot=0; 42 int cnt=0; 43 for(int i=1;i<=n;i++){ 44 if((x&(1<<(i-1)))==0) tot+=p[i]; 45 else cnt++; 46 } 47 if(cnt>=k){ 48 if(cnt>k) return 0; 49 for(int i=1;i<=n;i++){ 50 if(x&(1<<(i-1))) ans[i]+=f[x]; 51 } 52 return f[x]; 53 } 54 for(int i=1;i<=n;i++){ 55 if((x&(1<<(i-1)))==0){ 56 int t=x|(1<<(i-1)); 57 f[t]+=f[x]*(p[i]/tot); 58 } 59 } 60 return f[x]; 61 } 62 int main(){ 63 // fre(); 64 scanf("%d%d",&n,&k); 65 int m=n; 66 for(int i=1;i<=n;i++){ 67 cin>>p[i]; 68 if(p[i]<=1e-10) 69 m--; 70 } 71 k=min(m,k); 72 for(int i=0;i<(1<<n);i++) dp(i); 73 for(int i=1;i<=n;i++) printf("%.9lf ",(double)ans[i]); 74 return 0; 75 }
时间: 2024-10-12 13:03:12