BZOJ2302: [HAOI2011]Problem c

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2302

组合数学+dp(其实我完全不会。。。

首先题目转化成<=i的至少有i个,因为如果没有i个的话后面n-i个位置肯定是不够的。

然后dp,记录下必选点和可选点个数,然后做一个n^3的dp

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<cstring>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define maxn 305
#define ll long long
#define eps 1e-6
using namespace std;
int n,m,t;
ll c[maxn][maxn],f[maxn][maxn],M;
int cnt[maxn],sum[maxn];
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)) {if (ch==‘-‘) f=-1; ch=getchar();}
    while (isdigit(ch)) {x=x*10+ch-‘0‘; ch=getchar();}
    return x*f;
}
void init(){
    clr(cnt,0); clr(sum,0); clr(f,0); clr(c,0);
    c[0][0]=1;
    rep(i,1,n){
        c[i][0]=1;
        rep(j,1,i) c[i][j]=(c[i-1][j-1]+c[i-1][j])%M;
    }
}
int main(){
    t=read();
    while (t--){
        int x,y,gg;
        n=read(); m=read(); M=read();
        init();
        sum[0]=n-m;
        rep(i,1,m){
            x=read(); y=read(); cnt[y]++;
        }
        gg=0;
        rep(i,1,n) {
            sum[i]=sum[i-1]+cnt[i];
            if (sum[i]<i) {
                puts("NO"); gg=1;
                break;
            }
        }
        if (gg) continue;
        f[0][0]=1;
        rep(i,1,n)
            rep(j,i,sum[i])
                rep(k,cnt[i],j-i+1) {
                    f[i][j]=(f[i][j]+f[i-1][j-k]*c[sum[i]-j+k-cnt[i]][k-cnt[i]])%M;
                }
        printf("YES %lld\n",f[n][n]);
    }
    return 0;
}
时间: 2024-12-29 09:38:30

BZOJ2302: [HAOI2011]Problem c的相关文章

BZOJ2302 [HAOI2011]Problem c 【dp】

题目 给n个人安排座位,先给每个人一个1~n的编号,设第i个人的编号为ai(不同人的编号可以相同),接着从第一个人开始,大家依次入座,第i个人来了以后尝试坐到ai,如果ai被占据了,就尝试ai+1,ai+1也被占据了的话就尝试ai+2,--,如果一直尝试到第n个都不行,该安排方案就不合法.然而有m个人的编号已经确定(他们或许贿赂了你的上司...),你只能安排剩下的人的编号,求有多少种合法的安排方案.由于答案可能很大,只需输出其除以M后的余数即可. 输入格式 第一行一个整数T,表示数据组数 对于每

BZOJ 2302: [HAOI2011]Problem c( dp )

dp(i, j)表示从i~N中为j个人选定的方案数, 状态转移就考虑选多少人为i编号, 然后从i+1的方案数算过来就可以了. 时间复杂度O(TN^2) --------------------------------------------------------------------- #include<cstdio> #include<algorithm> #include<cstring> using namespace std; typedef long lo

[BZOJ 2301] [HAOI2011] Problem b

2301: [HAOI2011]Problem b Time Limit: 50 SecMemory Limit: 256 MB Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数n,接下来n行每行五个整数,分别表示a.b.c.d.k Output 共n行,每行一个整数表示满足要求的数对(x,y)的个数 Sample Input 2 2 5 1 5

BZOJ 2301([HAOI2011]Problem b-mobius反演)

2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MB Submit: 2170  Solved: 934 [Submit][Status][Discuss] Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数n,接下来n行每行五个整数,分别表示a.b.c.d.k Out

BZOJ 2301 [HAOI2011]Problem b (容斥+莫比乌斯反演+分块优化 详解)

2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MB Submit: 2096  Solved: 909 [Submit][Status][Discuss] Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数n,接下来n行每行五个整数,分别表示a.b.c.d.k Out

HAOI2011 problem b

其实就是容斥原理了 代码: 1 uses math; 2 const maxn=55000; 3 var i,n,a,b,c,d,w,tot:longint; 4 ans:int64; 5 sum,mu,p:array[0..maxn] of int64; 6 procedure get; 7 var i,j,k:longint; 8 check:array[0..maxn] of boolean; 9 begin 10 fillchar(check,sizeof(check),false);

BZOJ 2302: [HAOI2011]Problem c [DP 组合计数]

2302: [HAOI2011]Problem c Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 648  Solved: 355[Submit][Status][Discuss] Description 给n个人安排座位,先给每个人一个1~n的编号,设第i个人的编号为ai(不同人的编号可以相同),接着从第一个人开始,大家依次入座,第i个人来了以后尝试坐到ai,如果ai被占据了,就尝试ai+1,ai+1也被占据了的话就尝试ai+2,……,如果一直

2301: [HAOI2011]Problem b

2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 1737  Solved: 749[Submit][Status][Discuss] Description 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. Input 第一行一个整数n,接下来n行每行五个整数,分别表示a.b.c.d.k Outpu

【BZOJ2298】[HAOI2011]problem a DP

[BZOJ2298][HAOI2011]problem a Description 一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低.”问最少有几个人没有说真话(可能有相同的分数) Input 第一行一个整数n,接下来n行每行两个整数,第i+1行的两个整数分别代表ai.bi Output 一个整数,表示最少有几个人说谎 Sample Input 3 2 0 0 2 2 2 Sample Output 1 HINT 100%的数据满足: 1≤n≤100000   0≤