[SDOI2017] 硬币游戏

一、题目

点此看题

二、解法

一定要先完全搞懂 歌唱王国 那个题再来做这道题,一模一样的思路。

\(F_i(x)\) 表示 \(A_i\)(就表示那个硬币序列)在某个时刻出现的概率生成函数,\(G(x)\) 表示某个时刻还未结束的概率生成函数,现在就来找关系列方程吧!

有一个方程是最难列的,但是思路是固定的。我们考虑对于 \(A_i\) 直接在 \(G(x)\) 的基础上强行加一个长度为 \(m\) 的字符串构成 \(A_i\),但是可能会有其他的 \(A_j\) 中途就已经被构成了,所以可能没有加到 \(m\) 个字符就停止了!

但是这时候 \(A_i\) 的一个前缀一定等于 \(A_j\) 的一个后缀,我们枚举这个公共部分的长度,设 \(a_{i,j,k}\) 表示 \(A_i[1,k]=A_j[m-k+1,m]\),就可以结合 \(F_j(x)\) 列出这样的方程:

\[G(x)(\frac{x}{2})^m=\sum_{j=1}^n\sum_{k=1}^m a_{i,j,k}F_j(x)(\frac{x}{2})^{m-k} \]

\(x=1\) 带入,因为我们只需要求 \(F_i(1)\),系数和也是相等的:

\[G(1)=\sum_{j=1}^n\sum_{k=1}^ma_{i,j,k}F_j(1)2^k \]

这里已经有 \(n+1\) 个未知数和 \(n\) 个方程了,还有一个最简单的方程:

\[\sum_{i=1}^n F_i(1)=1 \]

直接高斯消元即可,时间复杂度 \(O(n^3)\)震惊,\(double\) 竟然可以存 \(2^{30}\)

#include <cstdio>
#include <iostream>
using namespace std;
const int M = 305;
#define db double
#define eps 1e-9
#define ull unsigned long long
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,m;char s[M];ull h[M][M],pw[M];db a[M][M],b[M];
ull Hash(int x,int l,int r)
{
	return h[x][r]-pw[r-l+1]*h[x][l-1];
}
db Abs(db x)
{
	return x>0?x:-x;
}
void guass(int n)
{
	for(int i=1;i<=n;i++)
	{
		int mx=i;
		for(int j=i+1;j<=n;j++)
			if(Abs(a[mx][i])<Abs(a[j][i]))
				mx=j;
		if(i!=mx) swap(a[i],a[mx]);
		for(int j=1;j<=n;j++)
		{
			if(i==j) continue;
			db t=a[j][i]/a[i][i];
			for(int k=i;k<=n+1;k++)
				a[j][k]-=a[i][k]*t;
		}
	}
}
signed main()
{
	n=read();m=read();pw[0]=b[0]=1;
	for(int i=1;i<=m;i++)
	{
		pw[i]=pw[i-1]*2;
		b[i]=b[i-1]*2;
	}
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		for(int j=1;j<=m;j++)
			h[i][j]=(s[j]=='H')+h[i][j-1]*2;
	}
	for(int i=1;i<=n;i++)//列第i个方程 
	{
		for(int j=1;j<=n;j++)
			for(int k=1;k<=m;k++)
				if(Hash(i,1,k)==Hash(j,m-k+1,m))
					a[i][j]+=b[k];
		a[i][n+1]=-1;
	}
	for(int i=1;i<=n;i++)
		a[n+1][i]=1;
	a[n+1][n+2]=1;
	guass(n+1);
	for(int i=1;i<=n;i++)
		printf("%.10f\n",a[i][n+2]/a[i][i]);
}
posted @ 2021-03-14 22:18  C202044zxy  阅读(64)  评论(0编辑  收藏  举报