题目链接:https://www.luogu.com.cn/problem/CF1286D
n个粒子,第i个在xi,速度是vi,有pi100的概率朝左飞,有1−pi100的概率往右飞,求期望第一对粒子碰撞的时间(如果永远没有碰撞则为0)
1≤n≤105
期望+最小值显然是不能直接搞的,我们可以考虑枚举最小值,因为第一次碰撞的一定是相邻的粒子,所以这样的情况最多只有2n种。
然后对于一个值作为最小值的时候有些情况是不被允许的,设fi,0/1表示在被允许情况且i向左/右的概率,此时每个转移可以写成一个2×2的矩阵,从大到小枚举最小值就可以每次只修改一个矩阵了,动态dp维护即可。
时间复杂度:O(23nlogn)
#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\n",ans);
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构