zoukankan      html  css  js  c++  java
  • SDOI2017硬币游戏

    枚举串,方便讨论


    (n,m300)

    很容易想到建出AC自动机后暴力高斯消元的(O(n^3m^3)40)分做法

    SOL:

    这题和CSTC2006歌唱王国很像

    定义:
    (a_{i,j,k})表示(A_i[1,k])是否等于(A_j[m-k+1,m])

    (f_{i,j})表示(A_i)出现时长度为(j)的概率,其生成函数为(F_i(X))

    (g_i)表示长度为(i)的序列未出现任何串的概率,其生成函数为(G(x))

    [G(x)+sum F_i(x)=1+G(x)*x ]

    对于任意一个串(i)

    [G(x)*frac 1{2^m}x^m=sum_{j=1}^nsum_{k=1}^ma_{i,j,k}*F_j(x)*frac 1{2^{m-k}}x^{m-k} ]

    (x=1)代入二试:

    [G(1)=sum^n_{j=1}sum^m_{k=1}a_{i,j,k}*F_j(1)*2^k ]

    需解出(G(1),F_i(1)),加上(sum F_i(1)=1),一共(n+1)个式子,高斯消元即可

    时间复杂度(O(n^3))

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	int x=0,f=1;char c=getchar();
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f==1?x:-x;
    }
    #define ll long long
    const int N=304,mod=1e9+7;
    const double eps=1e-10;
    int n,m,h[N][N],b[N];
    char s[N];
    double a[N][N],db[N];
    inline int hsh(int x,int l,int r){
    	return (h[x][r]-(ll)h[x][l-1]*b[r-l+1]%mod+mod)%mod;
    }
    inline void gauss(int n){
    	for(int i=1,id;i<=n;i++){
    		id=i;
    		for(int j=i+1;j<=n;j++)
    			if(fabs(a[j][i])>fabs(a[id][i]))id=i;
    		if(id!=i)swap(a[id],a[i]);
    		for(int j=i+1;j<=n;j++){
    			double tmp=a[j][i]/a[i][i];
    			for(int k=i;k<=n+1;k++){
    				a[j][k]-=a[i][k]*tmp;
    			}
    		}
    	}
    	for(int i=n;i;i--){
    		for(int j=i+1;j<=n;j++)
    			a[i][n+1]-=a[i][j]*a[j][n+1];
    		a[i][n+1]/=a[i][i];
    	}
    }
    int main(){
    	n=read();m=read();
    	b[0]=db[0]=1;
    	for(int i=1;i<=m;i++){
    		b[i]=(b[i-1]<<1)%mod;
    		db[i]=db[i-1]*2;
    	}
    	for(int i=1;i<=n;i++){
    		scanf("%s",s+1);
    		for(int j=1;j<=m;j++)
    			h[i][j]=((h[i][j-1]<<1)+(s[j]=='H'))%mod;
    	} 
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=n;j++)
    			for(int k=1;k<=m;k++)
    				if(hsh(i,1,k)==hsh(j,m-k+1,m))a[i][j]+=db[k];
    		a[i][n+1]=-1;
    	}
    	for(int i=1;i<=n;i++)
    		a[n+1][i]=a[n+1][n+2]=1;
    	gauss(n+1);
    	for(int i=1;i<=n;i++)
    		printf("%.8lf
    ",a[i][n+2]); 
    	return (0-0);
    }
    
  • 相关阅读:
    实例化讲解RunLoop---IOS
    IOS中的SpringBoard
    Mac版OBS设置详解
    Swift学习Tip之Closures
    Swift中Array的Map
    IOS中的国际化(一)
    IOS,中获取系统内存占有率的方法
    IOS获取两个日期之间的时间间隔
    IOS中微信支、支付宝支付详解
    IOS中的正则表达式:NSRegularExpression
  • 原文地址:https://www.cnblogs.com/aurora2004/p/12516678.html
Copyright © 2011-2022 走看看