zoukankan      html  css  js  c++  java
  • luogu P5279 [ZJOI2019]麻将

    传送门

    首先考虑怎么判断一堆牌里是否有个子集可以胡,首先7张对子比较好判,直接看个数(ge 2)的牌的总数,但是面子似乎不好贪心,考虑dp,设(f_{i,0/1,j,k})表示只有前(i)种牌的集合,是否有对子,以后要凑(j)(i-1,i,i+1)以及(k)(i,i+1,i+2),最多会有多少个面子.注意这里(j,k)(le 2)的,不然就可以搞出三个刻子,转移枚举(i+1)放多少张,然后枚举放多少个(i+1,i+2,i+3),然后枚举是否凑出一个对子,剩下的牌全部用来凑刻子进行转移

    然后如果一副牌胡了,也就是对子(ge 7),或者面子(ge 4)还有对子,那么就不能转移的,所以考虑搜出所有不能胡的集合,然后要把重复的状态判掉,发现这样所有的不胡的状态只有(2091)

    刚才搜状态的时候,可以发现这些状态构成了一个自动机,可以判断一副牌是否胡了.题目要求的是胡牌要摸多少牌的期望,根据期望的线性性可以看成摸了(i)张牌没有胡的概率之和.所以设(g_{i,j,k}),表示前(i)种牌,现在在自动机上的第(j)位,总共摸了(k)张牌的方案,转移枚举下一位放多少张,沿着自动机转移,还要乘上一个转移系数(就是组合数),最后算出的方案/总方案就是答案

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<map>
    #include<set>
    #define LL long long
    #define db double
    
    using namespace std;
    const int N=100+10,M=2100+10,mod=998244353;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    struct node
    {
        int mz[2][3][3],dz;
        node(){memset(mz,-1,sizeof(mz)),dz=0;}
        bool operator < (const node &bb) const
        {
            for(int i=0;i<=1;++i)
                for(int j=0;j<=2;++j)
                    for(int k=0;k<=2;++k)
                        if(mz[i][j][k]!=bb.mz[i][j][k]) return mz[i][j][k]<bb.mz[i][j][k];
            return dz<bb.dz;
       	}
    }emp;
    map<node,int> mp;
    int tt,go[M][5],n,cn[N],fac[N<<2],iac[N<<2],f[2][M][N<<2];
    int fpow(int a,int b){int an=1;while(b){if(b&1) an=1ll*an*a%mod;a=1ll*a*a%mod,b>>=1;} return an;}
    int C(int n,int m){return m<0||n<m?0:1ll*fac[n]*iac[m]%mod*iac[n-m]%mod;}
    bool hu(node x)
    {
        if(x.dz>=7) return 1;
        for(int j=0;j<=2;++j)
            for(int k=0;k<=2;++k)
                if(x.mz[1][j][k]>=4) return 1;
        return 0;
    }
    node trans(node x,int nm)
    {
        node nw;
        nw.dz=x.dz+(nm>=2);
        for(int i=0;i<=1;++i)
        {
            if(nm-i-i<0) continue;
            for(int m=i;m<=1;++m)
                for(int j=0;j<=2&&i+i+j<=nm;++j)
                    for(int k=0;k<=2&&i+i+j+k<=nm;++k)
                        for(int l=0;l<=2&&i+i+j+k+l<=nm;++l)
                            if(~x.mz[m^i][j][k])
                                nw.mz[m][k][l]=min(4,max(nw.mz[m][k][l],x.mz[m^i][j][k]+j+(nm-(i+i+j+k+l))/3));
        }
        return nw;
    }
    void inii(node x)
    {
        if(mp.find(x)!=mp.end()) return;
        mp[x]=++tt;
        for(int i=0;i<=4;++i)
        {
            node nt=trans(x,i);
            if(!hu(nt)) inii(nt);
            go[mp[x]][i]=mp[nt];
        }
    }
    
    int main()
    {
        emp.mz[0][0][0]=0;
        inii(emp);
        n=rd();
        for(int i=1;i<=13;++i) ++cn[rd()],rd();
        fac[0]=1;
        for(int i=1;i<=n*4;++i) fac[i]=1ll*fac[i-1]*i%mod;
        iac[n*4]=fpow(fac[n*4],mod-2);
        for(int i=n*4;i;--i) iac[i-1]=1ll*iac[i]*i%mod;
        int nw=1,la=0;
        f[la][1][0]=1;
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=tt;++j)
                for(int k=0;k<=n*4;++k)
                {
                    if(!f[la][j][k]) continue;
                    for(int l=cn[i];l<=4;++l)
                        if(go[j][l]) f[nw][go[j][l]][k+l]=(f[nw][go[j][l]][k+l]+1ll*f[la][j][k]*C(4-cn[i],l-cn[i])%mod)%mod;
                    f[la][j][k]=0;
                }
            nw^=1,la^=1;
        }
        int ans=0;
        for(int j=1;j<=tt;++j)
            for(int k=13;k<=n*4;++k)
                ans=(ans+1ll*f[la][j][k]*fac[k-13]%mod*fac[n*4-k]%mod)%mod;
        printf("%lld
    ",1ll*ans*iac[n*4-13]%mod);
        return 0;
    }
    
  • 相关阅读:
    flink 读取kafka 数据,partition分配
    Flink 报错 "Could not find a suitable table factory for 'org.apache.flink.table.factories.StreamTableSourceFactory' in the classpath"
    flume接收http请求,并将数据写到kafka
    【翻译】Flume 1.8.0 User Guide(用户指南) Processors
    【翻译】Flume 1.8.0 User Guide(用户指南) Channel
    【翻译】Flume 1.8.0 User Guide(用户指南) Sink
    【翻译】Flume 1.8.0 User Guide(用户指南) source
    【翻译】Flume 1.8.0 User Guide(用户指南)
    Apache Flink 简单安装
    Java之使用IDE
  • 原文地址:https://www.cnblogs.com/smyjr/p/10754467.html
Copyright © 2011-2022 走看看