zoukankan      html  css  js  c++  java
  • 洛谷P2523 [HAOI2011]Problem c(计数dp)

    题面

    luogu

    题解

    首先,显然一个人实际位置只可能大于或等于编号

    先考虑无解的情况

    对于编号为(i),如果确认的人编号在([i,n])中数量大于区间长度,那么就无解

    (S[i])表示确认的人编号在([i,n])中数量

    我们只要考虑剩下的(n - m)

    (f[i][j])表示编号(>=i)的,已经确认了(j)

    那么我们枚举多少人编号为(i)

    (f[i][j] = sum f[i + 1][j - k] * (^j_k))

    因为交换一些人的编号也是可行方案,所以乘上一个组合数

    Code

    #include<bits/stdc++.h>
    
    #define LL long long
    #define RG register
    
    using namespace std;
    template<class T> inline void read(T &x) {
    	x = 0; RG char c = getchar(); bool f = 0;
    	while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;
    	while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();
    	x = f ? -x : x;
    	return ;
    }
    template<class T> inline void write(T x) {
    	if (!x) {putchar(48);return ;}
    	if (x < 0) x = -x, putchar('-');
    	int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;
    	for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
    }
    
    const int N = 310;
    
    int n, m, Mod, s[N], f[N][N], C[N][N];
    void pls(int &x, int y) {
    	x += y;
    	if (x >= Mod) x -= Mod;
    }
    void solve() {
    	read(n), read(m), read(Mod);
    	for (int i = 0; i <= 300; i++) C[i][0] = C[i][i] = 1;
    	for (int i = 2; i <= 300; i++)
    		for (int j = 1; j < i; j++)
    			C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % Mod;
    	memset(s, 0, sizeof(s));
    	for (int i = 1, x; i <= m; i++) read(x), read(x), s[x]++;
    	for (int i = n; i; i--) s[i] += s[i + 1];
    	bool flag = 0;
    	for (int i = 1; i <= n; i++)
    		if (s[i] > n - i + 1) {
    			flag = 1;
    			break;
    		}
    	if (flag) {
    		puts("NO");
    		return ;
    	}
    	memset(f, 0, sizeof(f));
    	f[n + 1][0] = 1;
    	for (int i = n; i; i--)
    		for (int j = 0; j <= n - i + 1 - s[i]; j++)
    			for (int k = 0; k <= j; k++)
    				pls(f[i][j], 1ll * f[i + 1][j - k] * C[j][k] % Mod);
    	printf("YES %d
    ", f[1][n - m]);
    	return ;
    }
    
    int main() {
    	int T;
    	read(T);
    	while (T--) solve();
    	return 0;
    }
    
    
  • 相关阅读:
    小黄衫获奖感言
    原型设计
    20210326编程作业
    阅读任务
    准备工作
    cmd命令行批量修改文件名后缀
    【智能算法】模拟退火算法
    【智能算法】粒子群寻优算法
    【并行计算】基于OpenMP的并行编程
    Python科学计算——前期准备
  • 原文地址:https://www.cnblogs.com/zzy2005/p/10549356.html
Copyright © 2011-2022 走看看