题解 洛谷 P6835 [Cnoi2020]线形生物

感觉这道题好像出的水了点,像我这种对期望一窍不通的菜鸡也可以推出来。我的思路好像和大家不太一样(更简单一点吧)……但是好歹过了,大家可以参考一下。

我们设要通过第 x 个点需要的期望步数为 E(x)。那么我们可以根据定义推出 E(x) 的表达式:

E(x)=n+i=txxE(i)n

在这里,tx 表示所有 x 的返祖点。第一个求和符号枚举的是它的所有返祖边,第二个求和是要求从 tx 走到 x 的期望步数。显而易见,第二个求和可以前缀和优化。

我们令 S(x)=i=1xE(i)。那么原式可以写为:

E(x)=n+(n1)×S(x)S(tx1)n

S(x) 改为 E(x)+S(x1),再移项,就可以得到 E(x) 的公式:

E(x)=n+(n1)×S(x1)S(tx1)

至此可以 O(n+m) 计算了。维护一下 ES,从 1 开始枚举就可以了。

献上丑陋的代码。

#include<bits/stdc++.h>
using namespace std;
int x,y;
long long g[1000001],ans;
const long long mod=998244353;
int h[1000001],t[1000001],nxt[1000001],cnt;
long long E[1000001],S[1000001];
inline int read()
{
	char C;
	int F=1,ANS=0;
	while (C<'0'||C>'9')
	{
		if (C=='-') F=-1;
		C=getchar();
	}
	while (C>='0'&&C<='9')
	{
		ANS=ANS*10+C-'0';
		C=getchar();
	}
	return F*ANS;
}
inline void add(int x,int y)
{
	t[++cnt]=y;
	nxt[cnt]=h[x];
	h[x]=cnt;
}
int main()
{
	int id,n,m;
	cin >> id >> n >> m;
	for (int i=1;i<=m;i++) 
	{
		int x,y;
		x=read(),y=read();
		g[x]++;
		add(x,y);
	}
	for (int i=1;i<=n;i++)
	{
		E[i]=(g[i]+1+g[i]*(S[i-1]))%mod;
		long long res=0;
		for (int j=h[i];j;j=nxt[j]) 
		{
			res=(res+S[t[j]-1])%mod;
		}
		E[i]-=res;
		E[i]=(E[i]+mod)%mod;
		S[i]=(S[i-1]+E[i])%mod;
	}
	cout << S[n];
	return 0;
}
posted @   Little09  阅读(94)  评论(0编辑  收藏  举报
编辑推荐:
· .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语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示