• BZOJ 4820 [Sdoi2017]硬币游戏


    题解:

    设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;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    创建包含前后255天所有天数的视图。
    VC获取主机名和主机信息
    在PowerDesigner增加unique约束
    差集的几种计算方法
    动态列的处理(统计)。
    一个查询语句各个部分的执行顺序
    IDC机房跳线
    软件下载链接
    IDC装机检查思路
    运维工程师之IDC系列
  • 原文地址:https://www.cnblogs.com/zzyer/p/8493259.html
Copyright © 2020-2023  润新知