[题解]普转提day5
某些代码要配合my_std使用
T1铺设道路
没啥好说的,上洛谷自己搜去
思路也是差分,只不过要考虑向上凸与向下凹,分别统计
代码:
ll n,k,ans1,ans2,a[110000];
int main(){
IO::file();
n=read();k=read();
rep(i,1,n)a[i]=read();
rep(i,1,n+1){
if(a[i]-a[i-1]>k)ans1+=a[i]-a[i-1]-k;
if(a[i]-a[i-1]<-k)ans2+=-k-a[i]+a[i-1];
}
writeln(max(ans1,ans2));
IO::flush();
}
T2拒绝压行
我们会发现它的代码,返回的是将一个数去掉的逆序对个数
我们只要求出每个数产生逆序对的个数,以及总逆序对
用总的减去最多的就是答案
代码:
int ans,mx,sum,n,a[110000];
int main(){
IO::file();
n=read();
rep(i,1,n)a[i]=read();
rep(i,1,n){
sum=0;
rep(j,1,i-1)if(a[j]>a[i])sum++;
rep(j,i+1,n)if(a[j]<a[i])sum++;
ans+=sum;
mx=max(mx,sum);
}
write(ans/2-mx);
IO::flush();
}
T3晓美焰的逃亡
期望DP
有一句话:概率DP正着枚,期望DP倒着枚
由题,\(p_{i,j,0}+p_{i,j,1}+p_{i,j,2}\)=1
\(f_{i,j}\)表示在i,j的期望
然后又会得到一个式子\(f_{i,j}=p_1*f_{i,j+1}+p_2*f_{i+1,j}+p_0*f_{i,j}+2\)
+2是花费
手累,用\(p_i\)简写了,大家看得懂就行
最后解出关于\(f_{i,j}\)的方程,得到\(f_{i,j}\)=\({f_{i,j+1}*p_1+f_{i+1,j}*p_2+2} \over {1-p_0}\)
代码:
int n,m;
double f[1100][1100],p[1100][1100][3];
void solve(){
memset(f,0,sizeof(f));
memset(p,0,sizeof(p));
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%lf%lf%lf",&p[i][j][0],&p[i][j][1],&p[i][j][2]);
for(int i=n;i>0;i--)for(int j=m;j>0;j--)if(p[i][j][0]!=1)f[i][j]=(f[i+1][j]*p[i][j][2]+f[i][j+1]*p[i][j][1]+2.0)/(1-p[i][j][0]);
printf("%.3lf\n",f[1][1]);
}
int main(){
while(~scanf("%d%d",&n,&m))solve();
}
T4吸血鬼
被概率吓到了,其实挺水的
不妨设\(d_i\)是第\(i\)个人变成吸血鬼的期望天数,\(q_i\)为第\(i\)个人便成吸血鬼的概率
显然,要求的就是\(\Sigma d_i\),而\(d_i\)=\({1} \over {p_i}\)
而\(p_i\)=\({p_i*n*(n-i)} \over {n*(n-1)/2}\)
所以答案就显然了
代码:
int T,n;
double p,ans;
void solve(){
scanf("%d%lf",&n,&p);
ans=0.0;
for(double i=1;i<=n-1;i++)ans+=n*(n-1.0)/(2.0*p*i*(n-i));
printf("%.3lf\n",ans);
}
int main(){
scanf("%d",&T);
while(T--)solve();
}