[CSP-S模拟测试]:走路(期望DP+分治消元)

题目传送门(内部题100)


输入格式

  第一行两个整数$n,m$,接下来$m$行每行两个整数$u,v$表示一条$u$连向$v$的边。不保证没有重边和自环。


输出格式

  $n-1$行每行一个整数,第$i$行表示$k=i+1$时的答案。对$998244353$取模。


样例

样例输入:

3 6
1 1
1 2
2 1
2 2
1 3
3 1

样例输出:

4
5


数据范围与提示

数据范围:

  对于$25\%$的数据,$n\leqslant 50$。
  对于另外$20\%$的数据,前$m-1$条边满足$u<v$。
  对于另外$15\%$的数据,不存在$u,v$使得$u!=v$且$\min(u,v)>1$。
  对于$100\%$的数据,$1\leqslant n\leqslant 300,1\leqslant m\leqslant 10^5,1\leqslant u,v\leqslant n$。

提示:

  对于质数$p$和有理数$\frac{a}{b}(b\mod p>0)$,存在恰好一个整数$c$满足$0\leqslant c<p$且$a\equiv bc(\mod p)$,我们称$c$为$\frac{a}{b}$对$p$取模的结果。


题解

概率正着推,期望倒着推。

不妨设$f[i]$表示从$i$出发走到$k$的期望步数,那么可以列出式子:

$$f[i]=\sum \frac{f[j]}{du[i]}+1$$

$f[k]=0$

其中$j$是$i$的所有出边所能到达的点,$du[i]$则为$i$的出度。

那么枚举所有的$k$,然后暴力高斯消元即可拿到$25$分。

考虑优化,因为高斯消元中一段的值可以对很多$k$做贡献,所以我们可以用分治消元。

原理就是:对于区间$[l,r]$,先消$[mid+1,r]$,然后继续递归$[l,mid]$,递归之后再消$[l,mid]$,接着递归$[mid+1,r]$。

时间复杂度:$\Theta(n^3\log n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int n,m;
int du[301],top;
long long Map[301][302],ans[301];
long long qpow(long long x,long long y)
{
	long long res=1;
	while(y)
	{
		if(y&1)res=res*x%mod;
		x=x*x%mod;y>>=1;
	}
	return res;
}
void gauss(int x,int l,int r)
{
	long long inv=qpow(Map[x][x],mod-2);
	for(int i=1;i<=n+1;i++)Map[x][i]=Map[x][i]*inv%mod;
	for(int i=1;i<=n;i++)
	{
		if(i==x)continue;
		long long flag=Map[i][x];
		for(int j=l;j<=r;j++)
			Map[i][j]=(Map[i][j]-Map[x][j]*flag)%mod;
		Map[i][n+1]=(Map[i][n+1]-Map[x][n+1]*flag)%mod;
	}
}
void solve(int l,int r)
{
	if(l==r){ans[l]=(Map[1][n+1]+mod)%mod;return;}
	int mid=(l+r)>>1;int wzc[301][302];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n+1;j++)
			wzc[i][j]=Map[i][j];
	for(int i=mid+1;i<=r;i++)gauss(i,l,r);
	solve(l,mid);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n+1;j++)
			Map[i][j]=wzc[i][j];
	for(int i=l;i<=mid;i++)gauss(i,l,r);
	solve(mid+1,r);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		Map[u][v]++;du[u]++;
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
			Map[i][j]=Map[i][j]*qpow(du[i],mod-2)%mod;
		Map[i][i]+=(Map[i][n+1]=-1);
	}
	solve(1,n);
	for(int i=2;i<=n;i++)printf("%d\n",ans[i]);
}


rp++

原文地址:https://www.cnblogs.com/wzc521/p/11763678.html

时间: 2024-07-31 10:37:58

[CSP-S模拟测试]:走路(期望DP+分治消元)的相关文章

BZOJ 3143 HNOI2013 游走 期望DP+高斯消元

题目大意:给定一个无向连通图,我们需要给每条边附一个1~m的不重复的权值,使1到n的期望权值和最小 首先贪心思想是求出每条边的期望经过次数 然后对期望值最小的边附加m的权值,第二小的边附加m-1的权值,以此类推. 令f[i]为第i个点的期望经过次数 那么每条边的期望经过次数就是f[x]/d[x]+f[y]/d[y] 其中d[x]表示x的度数 那么显然有: f[1]=1+Σ[1->j]f[j]/d[j] f[i]=Σ[i->j]f[j]/d[j] (2<=i<=n-1) 其中f[n]

【BZOJ3143】[Hnoi2013]游走 期望DP+高斯消元

[BZOJ3143][Hnoi2013]游走 Description 一个无向连通图,顶点从1编号到N,边从1编号到M. 小Z在该图上进行随机游走,初始时小Z在1号顶点,每一步小Z以相等的概率随机选 择当前顶点的某条边,沿着这条边走到下一个顶点,获得等于这条边的编号的分数.当小Z 到达N号顶点时游走结束,总分为所有获得的分数之和. 现在,请你对这M条边进行编号,使得小Z获得的总分的期望值最小. Input 第一行是正整数N和M,分别表示该图的顶点数 和边数,接下来M行每行是整数u,v(1≤u,v

【BZOJ2337】[HNOI2011]XOR和路径 期望DP+高斯消元

[BZOJ2337][HNOI2011]XOR和路径 Description 题解:异或的期望不好搞?我们考虑按位拆分一下. 我们设f[i]表示到达i后,还要走过的路径在当前位上的异或值得期望是多少(妈呀好啰嗦),设d[i]表示i的度数.然后对于某条边(a,b),如果它的权值是1,那么f[b]+=(1-f[a])/d[a]:如果它的权值是0,那么f[b]+=f[a]/d[a],然后我们移个项,就变成了一堆方程组求解,直接高斯消元. 别忘了f[n]=0! #include <cstdio> #i

BZOJ 3270 博物馆 期望DP+高斯消元

题目大意:给定一张无向连通图,两个人初始各在某个点上,每个时刻每个人会不动或任选出边走,求两人最终期望在哪里相遇 把点数平方,原图上的两个点(x,y)变成新图上的一个点 然后令A为这个图的邻接矩阵(若两人在同一点上则没有出边,否则按概率转移),S为初始行向量(S[(a,b)]=1),ans为答案行向量 那么有ans=S+SA+SA^2+SA^3+... =S(I-A^+∞)/(I-A) =S/(I-A) 于是有ans*(I-A)=S 于是对I-A的转置求高斯消元即可. 和驱逐猪猡那题的思路很像.

【期望DP+高斯消元】 UVA 10828 Back to Kernighan-Ritchie

通道 题意:从1开始 每次等概率从一个点到和他相邻的点 有向 走到不能走停止 求停止时每个点的期望

【期望DP+高斯消元】 HDU 4418 Time travel

通道 题意:1个人在数轴上来回走,以pi的概率走i步i∈[1, m],给定n(数轴长度),m,e(终点),s(起点),d(方向),求从s走到e经过的点数期望 思路:E[x] = sum((E[x+i]+i) * p[i])(i∈[1, m]) ,(走i步经过i个点,所以是E[x+i]+i) E[x] = sum ((E[x+i]+i) * p[i])----> E[x] - sum(p[i]*E[x+i]) = sum(i*p[i]) 代码: #include <iostream> #i

BZOJ 1778 Usaco2010 Hol Dotp 驱逐猪猡 期望DP+高斯消元

题目大意:给定一个无向图,炸弹从1号节点出发,每个时刻有P/Q的概率爆炸,如果某个时刻没有爆炸,就会等概率沿着随机一条出边走到下一个城市,求最终每个城市的爆炸概率 #include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 330 using namespace std; int n,m,p,q;

期望dp+高斯消元+bfs——hdu4418

高斯消元又弄了半天.. 注意只要能建立矩阵,那就必定有解,所以高斯消元里可以直接return 1 #include<bits/stdc++.h> using namespace std; const int maxn = 205; const double esp = 1e-7; int n,m,x,y,d; double p[maxn],a[maxn][maxn],b[maxn]; int equ,var; int Gauss(){ for(int i=0;i<n;i++){ int

【BZOJ3640】JC的小苹果 概率DP+高斯消元

[BZOJ3640]JC的小苹果 Description 让我们继续JC和DZY的故事. “你是我的小丫小苹果,怎么爱你都不嫌多!” “点亮我生命的火,火火火火火!” 话说JC历经艰辛来到了城市B,但是由于他的疏忽DZY偷走了他的小苹果!没有小苹果怎么听歌!他发现邪恶的DZY把他的小苹果藏在了一个迷宫里.JC在经历了之前的战斗后他还剩下hp点血.开始JC在1号点,他的小苹果在N号点.DZY在一些点里放了怪兽.当JC每次遇到位置在i的怪兽时他会损失Ai点血.当JC的血小于等于0时他就会被自动弹出迷