2025.3.12概率与期望

概率

定义:一件事发生的机率。

期望

定义:$$E(x)=\sum_i^n p_i \times i$$

例题

单选错位

考虑相邻两题答案相同的概率应为:

\[\frac{\min(a_i,a_{i+1})}{a_i\times a_{i+1}} \]

可以理解为两道题都蒙对的概率是 \(\frac{1}{a_i} \times \frac{1}{a_{i+1}}\) ,而两个选项相同的情况只会出现在选项较少的题目中,为 \(\min(a_i,a_{i+1})\) ,故答案如上式,化简得答案为:

\[\sum_{i=1}^n \frac{1}{\max(a _i,a_{i+1})} \]

特别的,当 \(i=n\)\(\frac{1}{\max(a_1,a_n)}\)
代码如下:

#include<iostream>
#include<iomanip>
using namespace std;
const int N=1e7+10;
int n,A,B,C;
int a[N];
double ans=0;
int main(){
	scanf("%d%d%d%d%d", &n, &A, &B, &C, a + 1);
	for (int i = 2; i <= n; i++)
		a[i] = ((long long) a[i - 1] * A + B) % 100000001;
	for (int i = 1; i <= n; i++)
		a[i] = a[i] % C + 1;
	for(int i=1;i<=n;i++){
		if(i==n){
			ans+=1.0/(1.0*max(a[1],a[n]));
		}else{
			ans+=1.0/(1.0*max(a[i],a[i+1]));
		}
	}
	cout<<fixed<<setprecision(3)<<ans;
	return 0;
}

线形生物

定义 \(E_i\) 表示从 \(i\)\(i+1\) 的期望步数,那么就有

\[E_i=out_i+1+\sum_{j}^{Edge_x}E_j \]

对于 \(out_i+1\) 统计的是每个点的返祖边,而后一项可以通过前缀和优化掉。
代码如下:

#include<iostream>

using namespace std;
const int N=1e6+50;
const int p=998244353;
struct Edge{
	int to,nxt;
}e[2*N];
int head[2*N],tot;
int out[N];
void add(int u,int v){
	e[++tot].to=v;
	e[tot].nxt=head[u];
	head[u]=tot;
	return ;
}
int id,n,m;
int E[N];
int arr[N];
int ans=0;
int main(){
	cin>>id>>n>>m;
	for(int i=1;i<=m;i++){
		int u,v;
		cin>>u>>v;
		add(u,v);
		out[u]++;
	}
	for(int i=1;i<=n;i++){
		E[i]=out[i]+1;
		for(int j=head[i];j;j=e[j].nxt){
			E[i]=((E[i]+arr[i-1])%p-arr[e[j].to-1]+p)%p;
		}
		arr[i]=arr[i-1]+E[i],arr[i]%=p;
	}
	for(int i=1;i<=n;i++){
		ans+=E[i]%p;
		ans%=p;
	}
	cout<<ans;
	return 0;
}

换教室

发现 \(v\) 很小,可以直接 Floyd 求出最短路,方便后续转移。
定义 \(dp_{i,}{_{j,}}_{0/1}\) 表示当前到第 \(i\) 个房间,对于第 \(j\) 节课,我们上或不上。

#include<bits/stdc++.h>

using namespace std;
const int N=2e5+10;
const int M=1e6+10;
const double inf=1e16;
int n,m,v,e;
int f[310][310];
long double dp[2010][2010][2];
int c[2010],d[2010];
long double k[2010];
long double ans;
int main(){
	cin>>n>>m>>v>>e;
	for(int i=1;i<=n;i++){
		cin>>c[i];
	}
	for(int i=1;i<=n;i++){
		cin>>d[i];
	}
	for(int i=1;i<=n;i++){
		cin>>k[i];
	}
	memset(f,0x3f,sizeof(f));
	for(int i=1;i<=e;i++){
		int a,b,w;
		cin>>a>>b>>w;
		f[a][b]=f[b][a]=min(f[a][b],w);
	}
	for(int i=1;i<=v;i++){
		for(int j=1;j<=v;j++){
			for(int p=1;p<=v;p++){
				f[j][p]=min(f[j][p],f[j][i]+f[i][p]);
			}
		}
	}
	for(int i=1;i<=v;i++){
		f[i][i]=0;
		f[i][0]=f[0][i]=0;
	}
	for(int i=0;i<=n;i++){
		for(int j=0;j<=m;j++){
			dp[i][j][0]=dp[i][j][1]=inf;
		}
	}
	dp[1][0][0]=dp[1][1][1]=0;
	for(int i=2;i<=n;i++){
		dp[i][0][0]=dp[i-1][0][0]+f[c[i-1]][c[i]];
		for(int j=1;j<=min(i,m);j++){
			int c1=c[i-1],c2=d[i-1],c3=c[i],c4=d[i];
			dp[i][j][0]=min(dp[i][j][0],min(dp[i-1][j][0]+f[c1][c3],dp[i-1][j][1]+f[c1][c3]*(1-k[i-1])+f[c2][c3]*k[i-1]));
			dp[i][j][1]=min(dp[i][j][1],min(dp[i-1][j-1][0]+f[c1][c3]*(1-k[i])+f[c1][c4]*k[i],dp[i-1][j-1][1]+f[c2][c4]*k[i]*k[i-1]+f[c2][c3]*k[i-1]*(1-k[i])+f[c1][c4]*(1-k[i-1])*k[i]+f[c1][c3]*(1-k[i-1])*(1-k[i])));
//			cout<<dp[i][j][0]<<' '<<dp[i][j][1]<<'\n';
		}
	}
	ans=inf;
	for(int i=0;i<=m;i++) ans=min(ans,min(dp[n][i][0],dp[n][i][1]));
	cout<<fixed<<setprecision(2)<<ans;
	return 0;
}

奖励关

观察到 \(n\) 很小,依据题意考虑状压dp。
定义 \(dp_i{_,}{_j}\) 表示第 \(i\) 个抛出的礼物,礼物领取状态为 \(j\) 时的收益。剩下的直接做即可。最后将 \(dp_i{_,}{_j}\div n\) 得到平均值。

#include<bits/stdc++.h>

using namespace std;
const int N=2e5+10;
const int M=1e6+10;
int k,n;
int p[20],in[20];
double f[110][(1<<16)];
int main(){
	cin>>k>>n;
	for(int i=1;i<=n;i++){
		cin>>p[i];
		for(int j=1;;j++){
			int t;
			cin>>t;
			if(t==0) break;
			in[i]=in[i]|(1<<(t-1));
		}
	}
	for(int i=k;i>=1;i--){
		for(int j=0;j<(1<<n);j++){
			for(int q=1;q<=n;q++){
				if((j&in[q])==in[q]){
					f[i][j]+=max(f[i+1][j],f[i+1][j|(1<<(q-1))]+p[q]);
				}else{
					f[i][j]+=f[i+1][j];
				}
			}
			f[i][j]/=n;
		}
	}
	cout<<fixed<<setprecision(6)<<f[1][0];
	return 0;
}
posted @ 2025-03-13 20:17  Tighnari  阅读(22)  评论(0)    收藏  举报