# [SDOI2017]硬币游戏

### Description

$H$表示正面朝上， 用$T$表示反面朝上，扔很多次硬币后，会得到一个硬币序列。比如$HTT$表示第一次正面朝上，后两次反面朝上。

### Sample Input

3 3
THT
TTH
HTT


### Sample Output

0.3333333333
0.2500000000
0.4166666667


### HINT

$P_i=\frac{1}{2^m}P_0-\sum\limits_{j=1}^n\sum\limits_{k=1}^m[\mathrm{prefix}(i,k)==\mathrm{suffix}(j,k)]\frac{1}{2^{m-k}}P_j$

/*program from Wolfycz*/
#include<map>
#include<set>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Fi first
#define Se second
#define lMax 1e18
#define MK make_pair
#define iMax 0x7f7f7f7f
#define sqr(x) ((x)*(x))
#define pii pair<int,int>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
int f=1; char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
return x*f;
}
inline void print(int x){
if (x<0)	putchar('-'),x=-x;
if (x>9)	print(x/10);
putchar(x%10+'0');
}
const int N=3e2;
double Pow[N+10];
void Get_Nxt(int *a,int *nxt,int n){
for (int i=2,j=0;i<=n;i++){
while (j&&a[j+1]!=a[i]) j=nxt[j];
if (a[j+1]==a[i])   j++;
nxt[i]=j;
}
}
void solve(int *x,int *y,int *nxt,int n,double &p){
int j=0;
for (int i=1;i<=n;i++){
while (j&&x[j+1]!=y[i]) j=nxt[j];
if (x[j+1]==y[i])   j++;
}
if (x==y)   j=nxt[j];
while (j){
p+=Pow[n-j];
j=nxt[j];
}
}
void Print(double *a,int n){
for (int i=0;i<=n;i++)
printf("%5g%c",a[i],i==n?'\n':' ');
}
char Coin[N+10];
int A[N+10][N+10],Nxt[N+10][N+10];
double B[N+10][N+10];
void Gauss(int n){
for (int i=0;i<=n;i++){
if (B[i][i]==0)
for (int j=i+1;j<=n;j++)
if (B[j][i]!=0)
for (int k=i;k<=n+1;k++)
swap(B[i][k],B[j][k]);
double temp=B[i][i];
for (int j=i;j<=n+1;j++)    B[i][j]/=temp;
for (int j=0;j<=n;j++){
if (i==j)   continue;
double _temp=B[j][i];
for (int k=0;k<=n+1;k++)
B[j][k]-=B[i][k]*_temp;
}
}
}
int main(){
Pow[0]=1;
for (int i=1;i<=N;i++)  Pow[i]=Pow[i-1]/2;
for (int i=1;i<=n;i++){
scanf("%s",Coin+1);
for (int j=1;j<=m;j++)
A[i][j]=Coin[j]=='T';
Get_Nxt(A[i],Nxt[i],m);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
solve(A[i],A[j],Nxt[i],m,B[i][j]);
for (int i=1;i<=n;i++){
B[i][0]-=Pow[m];
B[i][i]+=1;
}
for (int i=1;i<=n;i++)  B[0][i]=1;
B[0][n+1]=1;
Gauss(n);
for (int i=1;i<=n;i++)  printf("%.10lf\n",B[i][n+1]);
return 0;
}

posted @ 2022-01-09 20:52  Wolfycz  阅读(37)  评论(0编辑  收藏  举报