题解:
设N为任何人都没获胜的状态
设仅有两个人
A=TTH B=HTT
另P(NTTH)表示出现NTTH串的概率,为0.125
另P(A)表示A获胜的概率
跟距前后缀关系列方程
则P(NTTH)=P(A)+0.25P(B)+0.5P(B)
三个人的话同理即可
还有P(A)+P(B)==1
n+1个变量,n+1个方程,高斯消元即可
出现的问题:
n和m不相等,不要用n的范围去预处理m
有的数组需要开两倍
自己理解的还不够深刻
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
const int maxn=309;
int n,m;
char s[maxn][maxn];//people place
double fac[maxn];
double a[maxn][maxn];
char ss[maxn<<1];
int f[maxn<<1];
double Geta(int x,int y){
double ret=0;
for(int i=1;i<=m;++i)ss[i]=s[x][i];
for(int i=1;i<=m;++i)ss[i+m]=s[y][i];
f[1]=f[2]=1;
for(int i=2;i<=m+m;++i){
int j=f[i];
while((j!=1)&&(ss[i]!=ss[j]))j=f[j];
if(ss[i]==ss[j])f[i+1]=j+1;
else f[i+1]=1;
}
int j=m+m+1;
while(f[j]>m)j=f[j];
while(f[j]!=1){
ret+=fac[m-f[j]+1];
j=f[j];
}
return ret;
}
double douabs(double x){
if(x<0)return -x;
else return x;
}
void Guass(int n){
for(int j=1;j<=n;++j){
int maxline=j;
for(int i=j+1;i<=n;++i){
if(douabs(a[i][j])>douabs(a[maxline][j]))maxline=i;
}
if(maxline!=j){
for(int k=j;k<=n+1;++k)swap(a[j][k],a[maxline][k]);
}
for(int i=j+1;i<=n;++i){
double tmp=a[i][j]/a[j][j];
for(int k=j;k<=n+1;++k){
a[i][k]=a[i][k]-tmp*a[j][k];
}
}
}
// for(int i=1;i<=n;++i){
// for(int j=1;j<=n;++j){
// cout<<a[i][j]<<' ';
// }
// cout<<endl;
// }
for(int i=n;i>=1;--i){
for(int j=i+1;j<=n;++j){
a[i][n+1]=a[i][n+1]-a[i][j]*a[j][n+1];
}
a[i][n+1]/=a[i][i];
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%s",s[i]+1);
fac[0]=1;
for(int i=1;i<=m;++i)fac[i]=fac[i-1]*0.5;
for(int i=1;i<=n;++i){
for(int j=1;j<=n;++j){
a[i][j]=Geta(i,j);
}
a[i][i]+=1;
a[i][n+1]=-fac[m];
a[i][n+2]=0;
}
for(int i=1;i<=n;++i)a[n+1][i]=1;
a[n+1][n+1]=0;a[n+1][n+2]=1;
Guass(n+1);
for(int i=1;i<=n;++i)printf("%.10f
",a[i][n+2]);
return 0;
}