zoukankan      html  css  js  c++  java
  • ●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)?'
    ':' ');
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    383. Ransom Note
    598. Range Addition II
    453. Minimum Moves to Equal Array Elements
    492. Construct the Rectangle
    171. Excel Sheet Column Number
    697. Degree of an Array
    665. Nondecreasing Array
    视频网站使用H265编码能提高视频清晰度吗?
    现阶段的语音视频通话SDK需要解决哪些问题?
    企业远程高清会议平台视频会议系统在手机端使用的必备要求有哪些?
  • 原文地址:https://www.cnblogs.com/zj75211/p/8543054.html
Copyright © 2011-2022 走看看