您的位置:首页 > Web前端 > JavaScript

BZOJ:4820: [Sdoi2017]硬币游戏&&BZOJ:1444: [Jsoi2009]有趣的游戏(高斯消元求概率)

2017-04-17 20:50 645 查看

1444: [Jsoi2009]有趣的游戏

4820: [Sdoi2017]硬币游戏

这两道题都是关于不断随机生成字符后求出现给定字符串的概率的问题。

第一题数据范围较小,将串建成AC自动机以后,以AC自动机上每个点为一个未知数,列出方程高斯消元求解即可,时间复杂度$O(n^{3}m^{3})$。

#include<queue>
#include<cstdio>
#include<algorithm>
#define MN 321
#define ld double
#define eps 1e-12
using namespace std;

int n,m,l,mo[MN],num=0,ne[MN<<1];
char s[MN][MN],c[MN<<1];
ld a[MN][MN],S,two[MN];
ld abs(ld a){return a<0?-a:a;}
inline void Gauss(){
int i,j,k;
for (i=0;i<=num;i++){
for (j=i;j<=num;j++) if (abs(a[j][i])>eps) break;
for (k=0;k<=num+1;k++) swap(a[i][k],a[j][k]);
for (j=0;j<=num;j++)
if (j!=i)
for (S=a[j][i]/a[i][i],k=0;k<=num+1;k++) a[j][k]-=S*a[i][k];

}
}
int main(){
register int i,j,k,l;
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++) scanf("%s",s[i]);

for (two[0]=1,i=1;i<=m;i++) two[i]=two[i-1]*0.5;
for (i=1;i<=n;i++)
for (a[i][0]=-two[m],j=1;j<=n;j++){
for (k=0;k<m;k++) c[k]=s[i][k],c[m+m-k-1]=s[j][m-k-1];c[m+m]=0;
ne[0]=-1;
for (k=1;k<m+m;ne[k]=l+(c[l+1]==c[k]),k++)
for (l=ne[k-1];l!=-1&&c[l+1]!=c[k];l=ne[l]);
for (k=ne[k-1];k!=-1;k=ne[k])
if (k<m) a[i][j]+=two[m-1-k];
}

for (i=1;i<=n+1;i++) a[0][i]=1;
num=n;Gauss();
for (i=1;i<=n;i++) printf("%.8lf\n",a[i][n+1]/a[i][i]+eps);
}


4820: [Sdoi2017]硬币游戏
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: