zoukankan      html  css  js  c++  java
  • 题解 【[HAOI2011]Problem c】

    写在题解之前:感谢 \(\texttt{rfy}\) 大佬的讲解。


    【题目描述】

    \(n\) 个人安排座位,先给每个人一个 \(1\)~\(n\) 的编号,设第 \(i\) 个人的编号为 \(a_i\)(不同人的编号可以相同),

    接着从第一个人开始,大家依次入座,第 \(i\) 个人来了以后尝试坐到 \(a_i\),如果 \(a_i\) 被占据了,就尝试 \(a_i+1\)\(a_i+1\) 也被占据了的话就尝试 \(a_i+2,……,\) 如果一直尝试到第 \(n\) 个都不行,该安排方案就不合法。

    然而有 \(m\) 个人的编号已经确定(他们或许贿赂了你的上司...),你只能安排剩下的人的编号,求有多少种合法的安排方案。

    由于答案可能很大,只需输出其除以 \(M\) 后的余数即可。

    【输入格式】

    第一行一个整数 \(T\),表示数据组数。

    对于每组数据,第一行有三个整数,分别表示 \(n\)\(m\)\(M\)

    \(m\) 不为 \(0\),则接下来一行有 \(m\) 对整数,\(p_1\)\(q_1\)\(p_2\)\(q_2\) ,…, \(p_m\)\(q_m\),其中第 \(i\) 对整数 \(p_i\)\(q_i\) 表示第 \(p_i\) 个人的编号必须为 \(q_i\)

    【输出格式】

    对于每组数据输出一行,若是有解则输出 \(\text{YES}\),后跟一个整数表示方案数 \(\mod M\) ,注意,\(\text{YES}\) 和数之间只有一个空格,否则输出 \(\text{NO}\)

    【样例输入】

    2
    4 3 10
    1 2 2 1 3 1
    10 3 8882
    7 9 2 9 5 10    
    

    【样例输出】

    YES 4
    NO
    

    【数据范围与提示】

    \(100\%\) 的数据满足:\(1\leq T\leq 10\)\(1\leq n\leq 300\)\(0\leq m\leq n\)\(2\leq M\leq 10^9\)\(1\leq pi,qi\leq n\) 且保证 \(p_i\) 互不相同。


    我们考虑一个合法的方案满足的条件,即对于任意一个编号 \(i\) 的数,都需要保证编号小于等于 \(i\) 的人数大于等于 \(i\)

    反正法:反正它是对的。

    反证法:假设编号小于等于 \(i\) 的人数小于 \(i\)
    那么,编号大于 \(i\) 的人数就大于 \(n-i\) 后面的人数就超出限制,所以不合法。

    所以我们用 \(s_i\) 来表示编号小于等于 \(i\) 的人数,如果不合法则直接输出 NO。

    同时,用 \(num_i\) 来记录编号为 \(i\) 位上有几个人。

    考虑用 dp 来进行状态转移。

    \(f(i,j)\) 表示有 \(j\) 个人的编号小于等于 \(i\) 的情况。

    我们设编号确定为 \(i\) 的有 \(k\) 人,所以编号小于 \(i\) 的也就有 \(j-k\) 个人,而且第 \(i\) 位要从非限制的人中选 \(k-num_i\) 位,就可以得到:

    \(f(i,j)=f(i,j)+f(i-1,j-k) \times C(s_i-j+k-num_i,k-num_i)\)

    最后的答案就是 \(f(n,n)\)

    \(p.s.\) YES 和 NO 一定要大写QAQ。


    代码如下:

    #include<bits/stdc++.h>
    #define rint register int
    using namespace std;
    inline int read(){
        int s=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=0;c=getchar();}
        while(c>='0'&&c<='9')s=(s<<1)+(s<<3)+c-48,c=getchar();
        return f?s:-s;
    }
    int n,m,Mod,f[310][310],C[310][310];
    int num[310],s[310];
    void pre_work(){	
        C[0][0]=C[1][0]=C[1][1]=1;
        for(rint i=2;i<=n;i++){
            C[i][0]=1;
            for(rint j=1;j<=n;j++)
                C[i][j]=1ll*(C[i-1][j]+C[i-1][j-1])%Mod;
        }
    }
    int main(){
        int T=read();
        while(T--){
            memset(num,0,sizeof num);
            memset(s,0,sizeof s);
            memset(f,0,sizeof f);
            n=read(); m=read(); Mod=read();
            pre_work();
            for(rint i=1;i<=m;++i) read(),num[read()]++;
            s[0]=n-m;
            bool flag(1);
            for(rint i=1;i<=n;++i){
                s[i]=s[i-1]+num[i];
                if(s[i]<i){
                    flag=0; break;
                }
            }
            if(!flag){
                printf("NO\n");
                continue;
            }
            f[0][0]=1;
            for(rint i=1;i<=n;++i)
                for(rint j=max(i,num[i]);j<=s[i];++j)
                    for(rint k=num[i];k<=j-i+1;++k)
                        f[i][j]=1ll*(f[i][j]+1ll*f[i-1][j-k]*C[s[i]-num[i]-j+k][k-num[i]]%Mod)%Mod;
            printf("YES %d\n",f[n][n]);
        }
        return 0;
    }
    
    
  • 相关阅读:
    我的WCF之旅(1):创建一个简单的WCF程序
    网页设计中颜色的搭配
    CSS HACK:全面兼容IE6/IE7/IE8/FF的CSS HACK
    UVa 1326 Jurassic Remains
    UVa 10340 All in All
    UVa 673 Parentheses Balance
    UVa 442 Matrix Chain Multiplication
    UVa 10970 Big Chocolate
    UVa 679 Dropping Balls
    UVa 133 The Dole Queue
  • 原文地址:https://www.cnblogs.com/LCGUO/p/12488935.html
Copyright © 2011-2022 走看看