NKOJ 4087 (SDOI 2017)硬幣遊戲(高斯消元)
阿新 • • 發佈:2019-02-02
P4087【SDOI2017】硬幣遊戲
問題描述
輸入格式
輸出格式
樣例輸入
3 3
THT
TTH
HTT
樣例輸出
0.3333333333
0.2500000000
0.4166666667
提示
這題顯然的想到高斯消元,關鍵是如何建立方程。
不妨設每個人贏的概率分別為
此題的關鍵在於假設一個狀態
舉個例子來說明,就以樣例為例。
這三個人分別猜的是
考慮第一個人勝利的概率,那麼如果在
但是顯然這樣不對,因為如果
那麼應該有
對應的係數就是對應串出現的概率。實際上,當某個串的一個字尾等於當前串的一個字首時,就會對當前串的概率造成影響。
由於此題資料較弱,可以暴力匹配。當然也可以用KMP。
程式碼:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#define N 1005
using namespace std;
int n,m;
char S[N][N];
double A[N][N],B[N],X[N];
void Gauss(int row,int col)
{
int i,j,x,y,MR;double t,tmp;
for(x=1,y=1,MR=1;x<=row&&y<col;x++,y++,MR=x)
{
for(i=x+1;i<=row;i++)if (abs(A[i][y])>abs(A[MR][y]))MR=i;
if(i!=x)for(i=1;i<=col;i++)swap(A[x][i],A[MR][i]);
if(!A[x][y]){x--;continue;}
for(i=x+1;i<=row;i++)
if(A[i][y])
{
t=A[i][y]/A[x][y];
for(j=y;j<=col;j++)A[i][j]-=A[x][j]*t;
}
}
for(i=row;i>=1;i--)
{
tmp=A[i][col];
for(j=i+1;j<col;j++)tmp-=X[j]*A[i][j];
X[i]=tmp/A[i][i];
}
for(i=1;i<=n;i++)printf("%.10lf\n",X[i]);
}
int main()
{
int i,j,k,p,t;
scanf("%d%d",&n,&m);B[0]=1.0;
for(i=1;i<=n;i++)scanf("%s",S[i]),A[i][i]=1.0;
for(i=1;i<=m;i++)B[i]=B[i-1]/2;
for(i=1;i<=n;i++)
{
A[i][n+1]=-1.0;
for(j=1;j<=n;j++)
for(k=1,t=0;k<m;k++,t=0)
{
while(k+t<m&&S[j][k+t]==S[i][t])t++;
if(k+t==m)A[i][j]+=B[k];
}
}
for(i=1;i<=n;i++)A[n+1][i]=1.0;A[n+1][n+2]=1.0;
Gauss(n+1,n+2);
}