题解:
设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; }