[题解]普转提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();
}
posted @ 2020-08-03 16:27  ZTC_ZTC  阅读(124)  评论(0编辑  收藏  举报