• 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;
    }
    
  • 相关阅读:
    Python基础笔记(五)
    Python基础笔记(四)
    Python基础笔记(三)
    Python基础笔记(二)
    Python基础笔记(一)
    分页存储过程
    MD Test
    vue路由的配置技巧
    Echarts的使用与配置项
    js中call,apply,bind之间的区别
  • 原文地址:https://www.cnblogs.com/smyjr/p/10754467.html
Copyright © 2020-2023  润新知