zoukankan      html  css  js  c++  java
  • 【题解】Luogu P5339 [TJOI2019]唱、跳、rap和篮球

    原题传送门

    这题zsy写的是(O(n^2)),还有NTT(O(n^2log n))的做法。我的是暴力,(O(frac{a b n}{4})),足够通过

    考虑设(f(i))表示序列中至少有(i)组人讨论cxk的方案数

    这样就珂以进行容斥,易知答案ans为:

    $$ans=sum_{i=0}^{Min(n/4,a,b,c,d)} (-1)^i f(i)$$

    我们考虑如何计算(f(i))

    如果视讨论cxk的组为一个元素,则一共有(n-3*i)个元素

    我们把问题转换成一个多重排列的方案数

    多重排列的方案数求法:

    现在有(m)个不同的元素,每个(i)元素有(a_i)个,那么方案数为

    $$(sum_{i=1}^m a_i)! imes prod_{i=1}^m frac{1}{a_i!}$$

    那么我们只要暴力计算即可

    #include <bits/stdc++.h>
    #define ll long long 
    #define N 2005
    #define mod 998244353
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    inline int Min(register int a,register int b)
    {
        return a<b?a:b;
    }
    int n,a,b,c,d,lim;
    ll fac[N],inv[N],f[N],res,ans; 
    int main()
    {
        n=read(),a=read(),b=read(),c=read(),d=read();
        fac[0]=fac[1]=inv[0]=inv[1]=1;
        for(register int i=2;i<=n;++i)
            fac[i]=fac[i-1]*i%mod;
        for(register int i=2;i<=n;++i)
            inv[i]=(mod-mod/i)*inv[mod%i]%mod;
        for(register int i=2;i<=n;++i)
            inv[i]=inv[i]*inv[i-1]%mod;
        lim=Min(n>>2,Min(Min(a,b),Min(c,d)));
        for(register int x=0,v;x<=lim;++x)
        {
            v=(x&1)?-1:1;
            for(register int i=0;i<=n;++i)
                f[i]=0;
            for(register int i=0;i<=a-x;++i)
                for(register int j=0;j<=Min(n-4*x-i,b-x);++j)
                    f[i+j]=(f[i+j]+inv[i]*inv[j])%mod;
            res=0;
            for(register int i=0;i<=c-x;++i)
                for(register int j=0;j<=Min(n-4*x-i,d-x);++j)
                    res=(res+inv[i]*inv[j]%mod*f[n-4*x-i-j])%mod;
            res=res*fac[n-3*x]%mod*inv[x]%mod;
            ans=(ans+v*res)%mod;
        }
        write(ans<0?ans+mod:ans);
        return 0;
    }
    
  • 相关阅读:
    面试中你能做到随机应变吗? 沧海
    QQ只是一场意外 沧海
    面 试 中 要 慎 言 沧海
    你会应对这些面试题吗? 沧海
    面 试 小 技 巧 沧海
    面试抓住最初三分钟至关重要 沧海
    面试的十二种高级错误 沧海
    几种有难度的面试 沧海
    面试技巧: 轻松过关10种方法 沧海
    面 试 细 节 一 点 通 沧海
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10922551.html
Copyright © 2011-2022 走看看