Dotp

首个数论题
求概率/期望
好吧可能是个弱点
其实就是哪种情况对应哪个点爆炸的概率
显然在第i秒爆炸的概率是前第i-1秒不爆的概率(阶段1)乘以在第i秒爆炸的概率(阶段2)(这样看就是满足乘法原理的)
然后这就是一个逼近无穷大的问题
接下来就是分析i秒到达哪个点
如果到达某个点的话,显然不能暴力模拟
但是如果是说问概率=问方案数/方案总数的话,这就很好办
显然可以套加乘原理求得到每个点的方案数和方案总数,乘以爆炸概率就行
然后就是把每个点的爆炸概率依照加法原理求和即可
然后这样一套操作下来,我们就会发现:
如果从j到i的话
爆炸概率f(i)=sigma(i-j)(f(j)x(1-p)/d(j)),p在第i秒爆炸概率,d(j)是点出度
对于起点需要特判加个1
然后就有一个n元的线性方程组
高消解方程即可

臭气弹
#include <bits/stdc++.h>
using namespace std;
const int M=90010,N=333;
int x[M],y[M],d[N],n;
double a[N][N];
void g(){
	double t;
	for(int i=1;i<=n;i++){
		int k=0;
		for(int j=i;j<=n;j++){
			if(fabs(a[j][i])>fabs(a[k][i])){
				k=j;
			}
		}
		for(int j=i;j<=n+1;j++){
			swap(a[i][j],a[k][j]);
		}
		for(int j=i+1;j<=n;j++){
			t=a[j][i]/a[i][i];
			for(int k=i;k<=n+1;k++){
				a[j][k]-=t*a[i][k];
			}
		}
	}
	for(int i=n;i>=1;i--){
		for(int j=i+1;j<=n;j++){
			a[i][n+1]-=a[i][j]*a[j][n+1];
		}
		a[i][n+1]/=a[i][i];
	}
}
int main(){
	int m,q,p;
	scanf("%d%d%d%d",&n,&m,&p,&q);
	for(int i=1;i<=m;i++){
		scanf("%d%d",&x[i],&y[i]);
		d[x[i]]++;
		d[y[i]]++;
	}
	for(int i=1;i<=m;i++){
		a[x[i]][y[i]]=((double)p/q-1)/d[y[i]];
		a[y[i]][x[i]]=((double)p/q-1)/d[x[i]];
	}
	for(int i=1;i<=n;i++){
		a[i][i]=1;
	}
	a[1][n+1]=(double)p/q;
	g();
	for(int i=1;i<=n;i++){
		printf("%.9lf\n",a[i][n+1]);
	}
	return 0;
}
posted @ 2022-02-17 20:04  2K22  阅读(151)  评论(1)    收藏  举报