分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 教程案例

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

发布时间:2023-09-06 01:44责任编辑:郭大石关键词:meta

题目传送门

  神奇的门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 }

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

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

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved