【JZOJ 6026】【GDOI2019模擬2019.2.23】飛行棋

Description

在這裏插入圖片描述

Solution

原題只要保留6位小數,

記錄每個人走j步到達終點的概率,當j足夠大時就可以滿足進精度要求,

證明一下爲什麼這樣可行:
我們走很多步依舊沒有到達終點的概率很小,而走這麼多步還依舊贏的概率更小,所以對答案的影響很小,

Code

#include <cstdio>
#include <algorithm>
#include <iostream>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
typedef double db;
const int N=152,M=600000;
int read(int &n)
{
	char ch=' ';int q=0,w=1;
	for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
	if(ch=='-')w=-1,ch=getchar();
	for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n;
db ans;
int a[N],b[N];
db f[2][N];
db f1[22][M+2];
db g[22][M+2],g1[M+2];
int main()
{
	freopen("feixingqi.in","r",stdin);
	freopen("feixingqi.out","w",stdout);
	int q,w;
	read(n),read(m);
	if(m==1)return printf("1.000000\n"),0;
	fo(i,1,n)read(a[i]);
	fo(i,1,m)read(b[i]);
	f[0][n]=1;
	fo(j,1,M)
	{
		int I=j&1,I1=!I;
		db t=f[I1][n]*6;
		f[I][n]=0;
		fod(i,n-1,n-6)
		{
			f[I][i]=t*0.16666666666666666666666666666666666666666666666666666667;
			t+=f[I1][a[i]]-f[I1][a[n]];
		}
		fod(i,n-7,1)
		{
			f[I][i]=t*0.16666666666666666666666666666666666666666666666666666667;
			t+=f[I1][a[i]]-f[I1][a[i+6]];
		}
		fo(i,1,m)f1[i][j]=f[I][b[i]];
	}
	fo(i,0,M)g[m+1][i]=1;
	fod(i,m,1)fod(j,M,0)
	{
		f1[i][j]+=f1[i][j+1];
		g[i][j]=f1[i][j]*g[i+1][j];
	}
	fo(i,0,M)g1[i]=1;
	fo(i,1,m)
	{
		ans=0;
		fo(j,0,M)
		{
			ans+=(g1[j]*g[i+1][j])*(f1[i][j]-f1[i][j+1]);
			g1[j]*=f1[i][j+1];
		}
		printf("%.6lf\n",ans);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章