[CTS2019]隨機立方體(容斥+組合數學)


這題七次方做法顯然,但由於我太菜了,想了一會發現也就只會這么多,而且別的毫無頭緒。發現直接做不行,那么,容斥!

f[i]為至少i個極值的方案,然后這里需要一些輔助變量,a[i]表示選出i個三維坐標均不相同的i個極大值的方案數,g[i]表示i個極大的數任意一個至少有一維坐標相同的點的個數,h[i]表示g[i]的極值可以同時存在的方案數,那么有f[i]=C(nml,g[i])a[i]h[i](nml-g[i])!。

a[i]很容易求得,就是(∏(n-j)(m-j)(l-j))/i!,其中j∈[0,i),g[i]更好求,就是nml-(n-i)(m-i)(l-i)

然后要進行一些關於上升冪的運算,我這里打不出式子(因為太菜了不會LaTeX),所以就不打了。注意維護g[i]的前綴積,具體細節看code吧。

#include<bits/stdc++.h>
using namespace std;
const int N=5e6+7,mod=998244353;
int n,m,l,k,mn,ans,fac[N],inv[N],a[N],f[N],g[N],h[N],pre[N];
int calc(int x){return 1ll*(n-x)*(m-x)%mod*(l-x)%mod;}
int qpow(int a,int b)
{
    int ret=1;
    while(b)
    {
        if(b&1)ret=1ll*ret*a%mod;
        a=1ll*a*a%mod,b>>=1;
    }
    return ret;
}
int C(int a,int b){return 1ll*fac[a]*inv[b]%mod*inv[a-b]%mod;}
int main()
{
    inv[0]=inv[1]=fac[0]=1;for(int i=2;i<N;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
    for(int i=1;i<N;i++)fac[i]=1ll*fac[i-1]*i%mod,inv[i]=1ll*inv[i-1]*inv[i]%mod;
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d",&n,&m,&l,&k);
        mn=min(n,min(m,l));
        a[0]=h[0]=pre[0]=1;
        for(int i=1;i<=mn;i++)a[i]=1ll*a[i-1]*calc(i-1)%mod;
        for(int i=1;i<=mn;i++)g[i]=(1ll*g[i-1]+calc(i-1)-calc(i)+mod)%mod;
        for(int i=1;i<=mn;i++)pre[i]=1ll*pre[i-1]*g[i]%mod;
        pre[mn]=qpow(pre[mn],mod-2);
        for(int i=mn;i;i--)pre[i-1]=1ll*pre[i]*g[i]%mod;
        for(int i=1;i<=mn;i++)f[i]=1ll*a[i]*pre[i]%mod;
        ans=0;
        for(int i=k;i<=mn;i++)
        if((i-k)&1)ans=(ans-1ll*C(i,k)*f[i]%mod+mod)%mod;
        else ans=(ans+1ll*C(i,k)*f[i])%mod;
        printf("%d\n",ans);
    }
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM