zoukankan      html  css  js  c++  java
  • CF1286D-LCC【动态dp,数学期望】

    正题

    题目链接:https://www.luogu.com.cn/problem/CF1286D


    题目大意

    (n)个粒子,第(i)个在(x_i),速度是(v_i),有(frac{p_i}{100})的概率朝左飞,有(1-frac{p_i}{100})的概率往右飞,求期望第一对粒子碰撞的时间(如果永远没有碰撞则为(0)

    (1leq nleq 10^5)


    解题思路

    期望+最小值显然是不能直接搞的,我们可以考虑枚举最小值,因为第一次碰撞的一定是相邻的粒子,所以这样的情况最多只有(2n)种。

    然后对于一个值作为最小值的时候有些情况是不被允许的,设(f_{i,0/1})表示在被允许情况且(i)向左/右的概率,此时每个转移可以写成一个(2 imes 2)的矩阵,从大到小枚举最小值就可以每次只修改一个矩阵了,动态(dp)维护即可。

    时间复杂度:(O(2^3nlog n))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const ll N=1e5+10,M=2e6+10,S=2,P=998244353;
    struct Matrix{
    	ll a[S][S];
    }c,f[N],w[N<<2];
    struct node{
    	ll op,w,x;
    	double cw;
    }d[N<<1];
    ll ans,n,cnt,inv[M],x[N],v[N],p[N];
    Matrix operator*(const Matrix &a,const Matrix &b){
    	memset(c.a,0,sizeof(c.a));
    	for(ll i=0;i<S;i++)
    		for(ll j=0;j<S;j++)
    			for(ll k=0;k<S;k++)
    				(c.a[i][j]+=a.a[i][k]*b.a[k][j]%P)%=P;
    	return c;
    }
    void Change(ll x,ll L,ll R,ll pos,const Matrix &val){
    	if(L==R){w[x]=val;return;}
    	ll mid=(L+R)>>1;
    	if(pos<=mid)Change(x*2,L,mid,pos,val);
    	else Change(x*2+1,mid+1,R,pos,val);
    	w[x]=w[x*2]*w[x*2+1];return;
    }
    bool cmp(node x,node y)
    {return x.cw>y.cw;}
    signed main()
    {
    	inv[1]=1;
    	for(ll i=2;i<=2e6;i++)inv[i]=P-inv[P%i]*(P/i)%P;
    	scanf("%lld",&n);
    	for(ll i=1;i<=n;i++)
    		scanf("%lld%lld%lld",&x[i],&v[i],&p[i]),p[i]=p[i]*inv[100]%P;
    	for(ll i=1;i<n;i++)d[++cnt]=(node){0,(x[i+1]-x[i])*inv[v[i]+v[i+1]]%P,i+1,(double)(x[i+1]-x[i])/((double)(v[i]+v[i+1]))};
    	f[1].a[0][1]=p[1];f[1].a[0][0]=P+1-p[1];
    	Change(1,1,n,1,f[1]);
    	for(ll i=1;i<n;i++){
    		f[i+1].a[0][1]=p[i+1];
    		if(v[i]>v[i+1])d[++cnt]=(node){1,(x[i+1]-x[i])*inv[v[i]-v[i+1]]%P,i+1,(double)(x[i+1]-x[i])/((double)(v[i]-v[i+1]))};
    		else f[i+1].a[1][1]=p[i+1];
    		if(v[i]<v[i+1])d[++cnt]=(node){-1,(x[i+1]-x[i])*inv[v[i+1]-v[i]]%P,i+1,(double)(x[i+1]-x[i])/((double)(v[i+1]-v[i]))};
    		else f[i+1].a[0][0]=P+1-p[i+1];
    		Change(1,1,n,i+1,f[i+1]);
    	}
    	sort(d+1,d+1+cnt,cmp);
    	ll last=(w[1].a[0][0]+w[1].a[0][1])%P;
    	for(ll i=1;i<=cnt;i++){
    		ll x=d[i].x;
    		if(d[i].op==0)f[x].a[1][0]=P+1-p[x];
    		else if(d[i].op==1)f[x].a[1][1]=p[x];
    		else f[x].a[0][0]=P+1-p[x];
    		Change(1,1,n,x,f[x]);
    		(ans+=(w[1].a[0][0]+w[1].a[0][1]-last+P)%P*d[i].w%P)%=P;
    		last=(w[1].a[0][0]+w[1].a[0][1])%P;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    jQuery插件开发模式
    优化布局
    jquery easyui 选项卡
    easy ui 点击行展开与折叠
    考拉海购技术支持的前世今生
    跑的好好的 Java 进程,怎么突然就瘫痪了
    Dubbo 如何成为连接异构微服务体系的最佳服务开发框架
    微服务治理实践:如何对单点异常进行自动摘除
    盘点阿里巴巴 15 款开发者工具
    千万创业者的自白:踩过坑才明白这些真相!
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15394970.html
Copyright © 2011-2022 走看看