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;
}

浙公网安备 33010602011771号