hihocoder 1166 期望dp+高斯消元

来源:互联网 发布:横截面数据是指同一 编辑:程序博客网 时间:2024/04/30 10:58

#1166 : 交换代数

时间限制:20000ms
单点时限:1000ms
内存限制:256MB

描述

少女幽香这几天正在学习交换代数,然而她什么也没有学会,非常痛苦。于是她开始玩起了一个简单的小游戏,来放松一下。
地面上一共有n个球,一开始有一些是黑色的,有一些是白色的。每次她随机选择一个区间(一共有n(n+1)/2个区间,每个区间有相等的概率被选择),把这个区间的颜色反转,即将该区间中白球变黑球,黑球变白球。
现在她想要知道期望情况下,多少次反转能够使得整个区间都是白色的。

输入

第一行n (1 <= n <= 20),表示球的数量。
接下来一行n个数,表示这些球的颜色,0表示白色,1表示黑色。

输出

一行一个实数,表示答案。你的答案与标准答案的绝对误差在10-4以内就算正确。

样例输入
20 1
样例输出
3.000000
#include <iostream>#include<stdio.h>#include<string.h>#include<algorithm>#include<math.h>#define eps 1e-9using namespace std;int b[25];int d[25];double a[25][25];double x[25];int n;double Gauss(){    int row, col, max_r;    int equ,var;    equ = var = n;    row = col = 0;    while(row < equ && col < var)    {        max_r = row;        for(int i = row+1; i < equ; i++)            if(fabs(a[i][col])-fabs(a[max_r][col]) > eps)                max_r = i;        if(max_r != row)            for(int j = col; j <= var; j++)                swap(a[row][j], a[max_r][j]);        if(fabs(a[row][col]) < eps)        {            col++;            continue;        }        for(int i = row+1; i < equ; i++)        {            if(fabs(a[i][col]) > eps)            {                double t = a[i][col]/a[row][col];                a[i][col] = 0.0;                for(int j = col+1; j <= var; j++)                    a[i][j] -= a[row][j]*t;            }        }        row++;        col++;    }    for(int i = equ-1; i >= 0; i--)    {        if(fabs(a[i][i]) < eps) continue;        double tmp = a[i][var];        for(int j = i+1; j < var; j++)            tmp -= a[i][j]*x[j];        x[i] = tmp/a[i][i];    }}int main(){    while(cin>>n)    {    for(int i=1;i<=n;i++)        cin>>b[i];    b[0]=0;b[n+1]=0;    int ans=0;    for(int i=0;i<=n;i++)      {          d[i]=b[i]^b[i+1];          if(d[i]==0)            ans++;      }      memset(d,0,sizeof(d));      memset(a,0,sizeof(a));      //dp[m]=m(m-1)/n(n-1)*dp[m-2]+(n-m)(n-m-1)/n(n-1)*dp[m+2]+2*m(n-m)/n(n-1)*dp[m]+1      n=n+1;//0-N 所以个数为n+1    for(int i=0;i<n;i++)    {         a[i][i]=1.0-2.0*i*(n-i)/(n*(n-1)*1.0);         if(i>=2)         a[i][i-2]=-(i*(i-1))/((n*(n-1))*1.0);         if(i<n-2)         a[i][i+2]=-(n-i)*(n-i-1)/(n*(n-1)*1.0);         a[i][n]=1;    }    Gauss();    printf("%lf\n",x[ans]);    }    return 0;}

0 0