luogu P2791 幼儿园篮球题

Posted smyjr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P2791 幼儿园篮球题相关的知识,希望对你有一定的参考价值。

传送门

先看我们要求的是什么,要求的期望就是总权值/总方案,总权值可以枚举进球的个数\(i\),然后就应该是\(\sum_i=0^k \binommi\binomn-mk-ii^l\),总方案是\(\binomnk\)

直接做显然不行,然后式子里有个\(i^l\),把它拆开,也就是\(\sum_j=0^l \binomijS_l,jj!\),代入原式\[\sum_i=0^k\binommi\binomn-mk-i\sum_j=0^l \binomijS_l,jj!\]\[\sum_j=0^l S_l,jj!\sum_i=0^k\binommi\binomij\binomn-mk-i\]\[\sum_j=0^l S_l,jj!\sum_i=0^k\binommj\binomm-ji-j\binomn-mk-i\]\[\sum_j=0^l S_l,jj!\binommj\sum_i=0^k\binomm-ji-j\binomn-mk-i\]\[\sum_j=0^l S_l,jj!\binommj\binomn-jk-j\]

然后只要能快速预处理出\(S_l,j\)就能做了.考虑组合意义\[S_n,m=\frac1m!\sum_i=0^m(-1)^i\binommi(m-i)^n\]\[S_n,m=\sum_i=0^m\frac(-1)^ii!\frac(m-i)^n(m-i)!\]

卷积即可

这题可能有点卡常,注意简化运算

// luogu-judger-enable-o2
#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=2e7+10,M=550000+10,mod=998244353;
LL rd()

    LL 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;

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 inv(int a)return fpow(a,mod-2);
int fac[N],iac[N],rdr[M];
void ntt(int *a,int n,bool op)

    int x,y;
    for(int i=0;i<n;++i)
        if(i<rdr[i]) swap(a[i],a[rdr[i]]);
    for(int i=1;i<n;i<<=1)
    
        int ww=fpow(op?3:332748118,(mod-1)/(i<<1));
        for(int j=0;j<n;j+=i<<1)
            for(int k=0,w=1;k<i;++k,w=1ll*w*ww%mod)
                x=a[j+k],y=1ll*a[j+k+i]*w%mod,a[j+k]=(x+y)%mod,a[j+k+i]=(x-y+mod)%mod;
    
    if(!op) for(int i=0,w=inv(n);i<n;++i) a[i]=1ll*a[i]*w%mod;

int C(int n,int m)return m<0||n<m?0:1ll*fac[n]*iac[m]%mod*iac[n-m]%mod;
int n,m,s,l,aa[M],bb[M],prm[M>>1],tt;
bool v[M];

int main()

    n=rd(),m=rd(),s=rd(),l=rd();
    fac[0]=1;
    int lm=max(n,l);
    for(int i=1;i<=lm;++i) fac[i]=1ll*fac[i-1]*i%mod;
    iac[lm]=inv(fac[lm]);
    for(int i=lm;i;--i) iac[i-1]=1ll*iac[i]*i%mod;
    bb[1]=1;
    for(int i=2;i<=l;++i)
    
        if(!v[i]) prm[++tt]=i,bb[i]=fpow(i,l);
        for(int j=1;j<=tt&&i*prm[j]<=l;++j)
        
            v[i*prm[j]]=1;
            bb[i*prm[j]]=1ll*bb[i]*bb[prm[j]]%mod;
            if(i%prm[j]==0) break;
        
    
    for(int i=0;i<=l;++i)
        aa[i]=(i&1)?mod-iac[i]:iac[i];
    for(int i=0;i<=l;++i)
        bb[i]=1ll*bb[i]*iac[i]%mod;
    int len=1,ms=0;
    while(len<=l+l) len<<=1,++ms;
    for(int i=0;i<len;++i) rdr[i]=(rdr[i>>1]>>1)|((i&1)<<(ms-1));
    ntt(aa,len,1),ntt(bb,len,1);
    for(int i=0;i<len;++i) aa[i]=1ll*aa[i]*bb[i]%mod;
    ntt(aa,len,0);
    while(s--)
    
        int nn=rd(),mm=rd(),kk=rd(),ans=0,lim=min(min(l,kk),mm);
        for(int i=0;i<=lim;++i)
            ans=(ans+1ll*aa[i]/**fac[i]%mod*iac[i]%mod*/*iac[mm-i]%mod*fac[nn-i]%mod*iac[kk-i]%mod)%mod;
        ans=1ll*ans*inv(C(nn,kk))%mod*fac[mm]%mod*(nn>=kk?iac[nn-kk]:0)%mod;
        printf("%d\n",ans);
    
    return 0;

以上是关于luogu P2791 幼儿园篮球题的主要内容,如果未能解决你的问题,请参考以下文章

Luogu P5339 [TJOI2019]唱跳rap和篮球

Luogu P5339 [TJOI2019]唱跳rap和篮球

[luogu5339] [TJOI2019]唱跳rap和篮球(容斥原理+组合数学)(不用NTT)

[luogu P3275] [SCOI2011]糖果

luogu 积木大赛

[Luogu2057]善意的投票