CF Edu Round 177 题解合集
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;
}

浙公网安备 33010602011771号