Codeforces 37D Lesson Timetable - 组合数学 - 动态规划

题目传送门

  神奇的门I

  神奇的门II

题目大意

  有$n$组学生要上课2次课,有$m$个教室,编号为$1$到$m$。要确定有多少种不同的安排上课的教室的方案(每组学生都是本质不同的),使得它们满足:

  • 每组学生第一次上课的教室的编号小于等于第二次上课的教室的编号。
  • 第$i$间教室在第一次上课时,恰好有$x_{i}$组学生在场。
  • 第$i$间教室在某次上课时,中间包含的学生组数不能超过$y_{i}$。

  输出答案模$10^{9} + 7$。

  因为第一次上课恰好有多少人,所以这个方案数是可以直接用组合数,暂时可以扔掉。

  对于第二次上课的时候,考虑用动态规划来做,用$f[i][j]$表示,考虑到第$i$个教室,当前一共还有$j$个人没有分配教室。

  转移的时候枚举在第$i$个教室中上课的人数,再乘一乘组合数就好了。

Code

 1 /**
 2  * Codeforces
 3  * Problem#37D
 4  * Accepted
 5  * Time: 46ms
 6  * Memory: 6388k
 7  */
 8 #include <bits/stdc++.h>
 9 using namespace std;
10
11 const int N = 1005, M = 105, mod = 1e9 + 7;
12
13 int n = 0, m;
14 int xs[M], ys[M];
15 int C[N][N];
16 int f[M][N];
17
18 inline void init() {
19     scanf("%d", &m);
20     for (int i = 1; i <= m; i++)
21         scanf("%d", xs + i), n += xs[i];
22     for (int i = 1; i <= m; i++)
23         scanf("%d", ys + i);
24 }
25
26 inline void solve() {
27     C[0][0] = 1;
28     for (int i = 1; i <= n; i++) {
29         C[i][0] = C[i][i] = 1;
30         for (int j = 1; j < i; j++)
31             C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod;
32     }
33
34     int s = 0, ans;
35     f[0][0] = 1;
36     for (int i = 1; i <= m; i++) {
37         s += xs[i];
38         for (int j = xs[i]; j <= s; j++)
39             for (int k = 0; k <= j && k <= ys[i]; k++)
40                 f[i][j - k] = (f[i][j - k] + f[i - 1][j - xs[i]] * 1ll * C[j][k]) % mod;
41     }
42     ans = f[m][0];
43     for (int i = 1; i <= m; i++) {
44         ans = (ans * 1ll * C[n][xs[i]]) % mod;
45         n -= xs[i];
46     }
47     printf("%d\n", ans);
48 }
49
50 int main() {
51     init();
52     solve();
53     return 0;
54 }

原文地址:https://www.cnblogs.com/yyf0309/p/8523627.html

时间: 2024-10-11 22:21:18

Codeforces 37D Lesson Timetable - 组合数学 - 动态规划的相关文章

Codeforces 223APartial Sums 数论+组合数学

题意很简单,求不是那么好求的,k很大 要操作很多次,所以不可能直接来的,印象中解决操作比较多无非线段树 循环节 矩阵 组合数等等吧,这道题目 也就只能多画画什么 的了 就以第一个案例为主吧 , 3 1 2 3 k我们依据画的次数来自己定好了 下面的每个数表示这个位置的 数由最初的 数组num[]中多少个数加起来得到的 当k为0的时候呢,就是 1 1 1 k为1的时候呢 1 2 3 k为2的时候呢 1 3 6 那么k为3的时候 1 4 10 这里看一下 从数组下标0开始,那么其实就是 C(i +

Codeforces 717A Festival Organization(组合数学:斯特林数+Fibonacci数列+推公式)

Codeforces 717A Festival Organization(组合数学:斯特林数+Fibonacci数列+推公式) 牛逼题.....推公式非常的爽...虽然我是看了别人的博客才推出来的... 0.1 斯特林数 下面要用到的是带符号的第一类斯特林数. \(x^{n\downarrow}=\prod_{i=0}^{n-1}(x-i)=\sum_{k=0}^ns(n,k)x^k\) 有递推公式\(s(n,m)=s(n-1,m-1)-(n-1)*s(n-1,m)\) 0.2 斐波那契数列的

计数 组合数学动态规划总结

本文持续更新 对计数,组合数学DP作总结,给出思路,状态转移方程,略去代码,状态初始值等. 1 划分数 m个不可区分的物品分成n份,每份的数量大于等于0,求划分的方法数. 思路: 若m < n, 则等价于m个物品划分为m份. 否则,若至少存在1份数量为0,则相当于m个物品划分为n - 1份;若每份数量大于等于1,则相当于m - n个物品划分为n份.动态规划或记忆化搜索. 2 HDU1502 Regular Words 给定n,求n个A,n个B,n个C组成的串的任意前缀中A的数量大于等于B的数量,

Codeforces 995F Cowmpany Cowmpensation - 组合数学

题目传送门 传送点I 传送点II 传送点III 题目大意 给定一个棵$n$个点的有根树和整数$D$,给这$n$个点标号,要求每个节点的标号是正整数,且不超过父节点的标号,根节点的标号不得超过D. 很容易地能得到$O(nD)$的动态规划:设$f[i][j]$表示$i$号点标为$j$在它的子树内的方案数. 写写它的转移方程:$f[i][j] = \prod_{s \in Son(i)}\sum_{k = 1}^{j} f[s][k]$. 设$g[i][j]=\sum_{k = 1}^{j}f[i][

Hihocoder #1075 : 开锁魔法III (组合数学+动态规划)

题目链接 题目大意:有n个箱子,每个箱子中放着一个箱子的钥匙,可以用魔法打开k个箱子,问最终能打开所有箱子的概率是多少. 思路:首先我们想到,如果一组箱子的打开目标能构成一个环,那么这个箱子中只要打开一个就随意了.问概率的话,最好想的做法就是用A事件发生的次数/事件总数.事件总数很好求,就是在n个箱子中选择k个打开:C[n][k]. 然后考虑有多少种合法的打开方式,我开始想的是直接用组合数学乱搞,乘法原理,设一共有tot个环,每个环的大小分别是a1,a2,a3...atot;计算的时候先a1*a

Codeforces 866C Gotta Go Fast - 动态规划 - 概率与期望 - 二分答案

You're trying to set the record on your favorite video game. The game consists of N levels, which must be completed sequentially in order to beat the game. You usually complete each level as fast as possible, but sometimes finish a level slower. Spec

Codeforces 1034C Region Separation - 数论 - 动态规划

题目传送门 传送站I 传送站II 传送站III 题目大意 给定一个$n$个点的树$T = (G, V)$,每个点有一个正整数点权$a_{i}$.整棵树是第1级划分.定义第$i$级划分是将第$i - 1$级划分中的每个区域划分成至少两个新的区域,并且所有区域都是一个连通块,每个点在每一级中只属于一个区域,在同一级划分内每个区域内的点的点权和相等.一种划分方案包含它划分的每一级.两种划分方案不同当且仅当它们划分的级数不同,或者存在一个点在某一级中它们在两种划分方案中属于不同区域. 之前好像某次noi

Codeforces 396A 数论,组合数学

题意:给一个a数组,求b 数组的方案数,但是要求两者乘积相同. 分析: 不可能将它们乘起来,对于每个数质因数分解,得到每个质因子个数,遍历这些质因子,将某个质因子放到 对应的盒子里面,可以不放,方案数就是一个组合数,用插板法. 这里的素数板子挺好的,一方面可以用来判断,一方面存起来. 组合数,可以考虑用乘法逆元. 每个质因子个数hash一下. #include <bits/stdc++.h> using namespace std; const int MOD = 1e9 + 7; #defi

CodeCraft-19 and Codeforces Round #537 (Div. 2) - D. Destroy the Colony(动态规划+组合数学)

Problem  CodeCraft-19 and Codeforces Round #537 (Div. 2) - D. Destroy the Colony Time Limit: 2000 mSec Problem Description Input Output For each question output the number of arrangements possible modulo 10^9+7. Sample Input abba21 41 2 Sample Output