码迷,mamicode.com
首页 > 其他好文 > 详细

[HAOI2011] Problem C - dp

时间:2020-03-01 21:45:31      阅读:50      评论:0      收藏:0      [点我收藏+]

标签:一个   cout   多少   int   lag   eof   const   注意   sig   

\(n\) 个人安排座位,每个人手上有一个编号 \(a_i\)。从第一个人开始依次进场,每个人进场后,会从 \(a_i\) 往后找到第一个空着的座位就做,如果没找到则这个方案不合法。现在有 \(m\) 个人的座位已经确定(不同人的编号可以相同),求有多少种合法的安排方案。 \(T\leq 10, n \leq 300\)

Solution

考虑怎样的情况的是无解的,设 \(s_i\) 表示编号既定的 \(m\) 人中编号 \(\geq i\) 的人数,对于 \(s_i>n-i+1\) 显然是无解的

类似地,设 \(f[i][j]\) 为普通人中,编号 \(\geq i\) 的人中确定了 \(j\) 个人的编号的方案数,那么考虑在确定了 \(j-k\) 人编号的情况下,选择 \(k\) 人编号为 \(i\) 来进行转移
\[ f[i][j]=\sum_{k=0}^j f[i+1][j-k]\cdot C_j^k,\ \ 0\leq j\leq n-s_i-i+1 \]
答案就是 \(f[1][n-m]\)

注意无解一定要先判掉,不能等最后利用答案判。

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 505;

int T,n,m,mod,p[N],q[N],f[N][N],c[N][N],s[N];

signed main() {
    ios::sync_with_stdio(false);
    cin>>T;
    while(T--) {
        memset(s,0,sizeof s);
        memset(f,0,sizeof f);
        memset(c,0,sizeof c);
        cin>>n>>m>>mod;
        c[0][0]=1;
        for(int i=1;i<=n;i++) {
            c[i][0]=1;
            for(int j=1;j<=i;j++) {
                c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
            }
        }
        for(int i=1;i<=m;i++) {
            cin>>p[i]>>q[i];
            s[q[i]]++;
        }
        for(int i=n;i>=0;--i) s[i]+=s[i+1];
        int flag=1;
        for(int i=1;i<=n;i++) if(s[i]>n-i+1) flag=0;
        if(flag==0) {
            cout<<"NO"<<endl;
            continue;
        }
        f[n+1][0]=1;
        for(int i=n;i>=1;--i) {
            for(int j=0;j<=n-s[i]-i+1;j++) {
                for(int k=0;k<=j;k++) {
                    (f[i][j]+=f[i+1][j-k]*c[j][k])%=mod;
                }
            }
        }
        cout<<"YES "<<f[1][n-m]<<endl;
    }
}

[HAOI2011] Problem C - dp

标签:一个   cout   多少   int   lag   eof   const   注意   sig   

原文地址:https://www.cnblogs.com/mollnn/p/12392042.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!