# @loj - 2004@ 「SDOI2017」硬币游戏

## @solution@

$G(x)x + 1 = G(x) + \sum_{i=1}^{n}F_i(x)$

$G(x)\times(\frac{1}{2})^m = \sum_{j=1}^{n}\sum_{k=1}^{m}[S_j[m-k...m-1] = S_i[0...k-1]]\times (\frac{1}{2})^{m - k}x^kF_j(x)$

$\sum_{i=1}^{n}F_i(1) = 1\\ \sum_{j=1}^{n}\sum_{k=1}^{m}[S_j[m-k...m-1] = S_i[0...k-1]]\times (\frac{1}{2})^{m - k}F_j(1) = G(1)\times(\frac{1}{2})^m$

## @accepted code@

#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std;

const int MAXN = 300;

double M[MAXN + 5][MAXN + 5];
void gauss(int n, int m) {
int r = 0, c = 0;
while( r < n && c < m ) {
int mxr = r;
for(int i=r+1;i<n;i++)
if( fabs(M[i][c]) >= fabs(M[mxr][c]) )
mxr = i;
if( mxr != r ) {
for(int j=c;j<m;j++)
swap(M[r][j], M[mxr][j]);
}
if( M[r][c] ) {
double k = M[r][c];
for(int j=c;j<m;j++)
M[r][j] /= k;
for(int i=0;i<n;i++) {
if( i == r ) continue;
k = M[i][c];
for(int j=c;j<m;j++)
M[i][j] -= k*M[r][j];
}
r++;
}
c++;
}
}

char s[MAXN + 5][MAXN + 5]; int n, m;
char t[2*MAXN + 5]; int f[2*MAXN + 5];
void get() {
for(int i=0;i<n;i++) {
for(int j=0;j<n;j++) {
for(int k=0;k<m;k++)
t[k] = s[i][k];
t[m] = '#';
for(int k=0;k<m;k++)
t[k+m+1] = s[j][k];
f[0] = -1, f[1] = 0;
for(int k=2;k<=2*m+1;k++) {
f[k] = f[k-1];
while( f[k] != -1 && t[f[k]] != t[k-1] )
f[k] = f[f[k]];
f[k]++;
}
int p = f[2*m + 1];
while( p ) {
M[i][j] += pow(2, -(m-p));
p = f[p];
}
}
//		M[i][n] = -pow(2, -m);
M[i][n] = -1;
}
for(int i=0;i<n;i++)
M[n][i] = 1;
M[n][n+1] = 1;
}

int main() {
scanf("%d%d", &n, &m);
for(int i=0;i<n;i++) scanf("%s", s[i]);
get(), gauss(n + 1, n + 2);
for(int i=0;i<n;i++)
printf("%.10f\n", M[i][n+1]);
}


## @details@

posted @ 2020-01-11 16:57  Tiw_Air_OAO  阅读(123)  评论(0编辑  收藏