CF Edu Round 177 题解合集

here.

D

考虑原问题等价于选择若干个字符种类,放到下标为奇数的位置,选择若干个字符种类,放到下标为偶数的位置。

然后考虑对于一种划分方案,它的贡献是奇偶两个集合的多重集排列数,也就是:

\[\frac{(\sum_{i\in S}c_i)!}{\prod_{i\in S}c_i!} \cdot\frac{(\sum_{i\notin S}c_i)!}{\prod_{i\notin S}c_i!} \]

发现这个贡献系数是不变的:

\[sum=\sum_{i=1}^{26} c_i \]

\[\frac{\frac{sum}{2}!(sum-\frac{sum}{2})!}{\prod_{i=1}^{26} c_i!} \]

所以我们只要计算集合 \(S\) 的个数即可,直接背包做到 \(O(kn)\)\(k=26\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353,maxn=5e5;
int binpow(int a,int b){
    if(!b) return 1;
    int res=binpow(a,b/2);
    if(b&1) return res*res%mod*a%mod;
    else return res*res%mod;
}
int t,n,ans,sum,c[27],fac[500005],inv[500005],f[500005];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    fac[0]=inv[0]=1;
    for(int i=1;i<=maxn;i++){
        fac[i]=fac[i-1]*i%mod;
        inv[i]=binpow(fac[i],mod-2);
    }
    cin>>t;
    n=26;
    while(t--){
        sum=0;
        ans=1;
        for(int i=1;i<=n;i++){
            cin>>c[i];
            sum+=c[i];
            ans=ans*inv[c[i]]%mod;
        }
        for(int i=0;i<=sum;i++) f[i]=0;
        f[0]=1;
        for(int i=1;i<=n;i++){
            if(!c[i]) continue;
            for(int j=sum;j>=c[i];j--){
                f[j]=(f[j]+f[j-c[i]])%mod;
            }
        }
        ans=ans*f[sum/2]%mod*fac[sum/2]%mod*fac[sum-sum/2]%mod;
        cout<<ans<<'\n';
    }
    return 0;
}

E

怎么一场全是计数来着。

考虑一个显然正确的谈心,每次选择最大的斑马数。

于是可以在这个贪心的基础上 DP。

\(f_{i,j}\) 表示 \([1,i]\) 中的数,由 \(j\) 个斑马数拼成的数的个数。

\(\le i\) 的最大斑马数为 \(maxn\),那么有:

\[f_{i,j}=f_{i-maxn,j-1}+f_{maxn-1,j} \]

初始 \(f_{0,0}=1\)

直接记忆化搜索即可。

复杂度 \(O(能过)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=998244353,maxn=5e5;
int binpow(int a,int b){
    if(!b) return 1;
    int res=binpow(a,b/2);
    if(b&1) return res*res%mod*a%mod;
    else return res*res%mod;
}
int t,n,ans,sum,c[27],fac[500005],inv[500005],f[500005];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    fac[0]=inv[0]=1;
    for(int i=1;i<=maxn;i++){
        fac[i]=fac[i-1]*i%mod;
        inv[i]=binpow(fac[i],mod-2);
    }
    cin>>t;
    n=26;
    while(t--){
        sum=0;
        ans=1;
        for(int i=1;i<=n;i++){
            cin>>c[i];
            sum+=c[i];
            ans=ans*inv[c[i]]%mod;
        }
        for(int i=0;i<=sum;i++) f[i]=0;
        f[0]=1;
        for(int i=1;i<=n;i++){
            if(!c[i]) continue;
            for(int j=sum;j>=c[i];j--){
                f[j]=(f[j]+f[j-c[i]])%mod;
            }
        }
        ans=ans*f[sum/2]%mod*fac[sum/2]%mod*fac[sum-sum/2]%mod;
        cout<<ans<<'\n';
    }
    return 0;
}
posted @ 2025-04-11 22:37  _Kenma  阅读(9)  评论(0)    收藏  举报