牛客练习赛71C-数学考试【容斥,dp】
正題
題目鏈接:https://ac.nowcoder.com/acm/contest/7745/C
題目大意
求一nnn的排列,給mmm個(gè)限制pip_ipi?表示1~pi1\sim p_i1~pi?不能是pip_ipi?的排列。求方案數(shù)。
解題思路
定義fif_ifi?表示1~pi1\sim p_i1~pi?是pip_ipi?的排列的情況下1~pi1\sim p_i1~pi?的方案數(shù),顯然有fi=pi!f_i=p_i!fi?=pi?!。但是如果我們用這個(gè)計(jì)算就會(huì)重復(fù),所以我們需要容斥。定義fif_ifi?表示1~pi1\sim p_i1~pi?是pip_ipi?的排列,且1~pk1\sim p_k1~pk?不是pkp_kpk?的排列(k<i)(k<i)(k<i)的情況下1~pi1\sim p_i1~pi?的方案數(shù),那么有轉(zhuǎn)移方程fi=pi!?∑j=1i?1fj?(pi?pj)!f_i=p_i!-\sum_{j=1}^{i-1}f_{j}*(p_i-p_j)!fi?=pi?!?j=1∑i?1?fj??(pi??pj?)!
然后答案ans=n!?∑i=1mfi?(n?pi)!ans=n!-\sum_{i=1}^mf_i*(n-p_i)!ans=n!?i=1∑m?fi??(n?pi?)!
時(shí)間復(fù)雜度O(m2)O(m^2)O(m2)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=2100,XJQ=20000311; ll n,m,fac[N],p[N],f[N]; int main() {scanf("%lld%lld",&n,&m);fac[0]=1;for(ll i=1;i<=n;i++)fac[i]=fac[i-1]*i%XJQ;for(ll i=1;i<=m;i++)scanf("%lld",&p[i]);sort(p+1,p+1+m);for(ll i=1;i<=m;i++){f[i]=fac[p[i]]%XJQ;for(ll j=1;j<i;j++)f[i]=(f[i]-f[j]*fac[p[i]-p[j]]%XJQ+XJQ)%XJQ;}ll ans=fac[n];for(ll i=1;i<=m;i++)ans=(ans-f[i]*fac[n-p[i]]%XJQ+XJQ)%XJQ;printf("%lld",ans); }總結(jié)
以上是生活随笔為你收集整理的牛客练习赛71C-数学考试【容斥,dp】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎样看建筑图纸 看建筑图纸的方法
- 下一篇: 过期药品属于什么垃圾 过期药品属于什么垃