Codeforces 37D-Lesson Timetable

Lesson Timetable
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

When Petya has free from computer games time, he attends university classes. Every day the lessons on Petya’s faculty consist of two double classes. The floor where the lessons take place is a long corridor with M classrooms numbered from 1 to M, situated along it.

All the students of Petya’s year are divided into N groups. Petya has noticed recently that these groups’ timetable has the following peculiarity: the number of the classroom where the first lesson of a group takes place does not exceed the number of the classroom where the second lesson of this group takes place.

Once Petya decided to count the number of ways in which one can make a lesson timetable for all these groups. The timetable is a set of 2N numbers: for each group the number of the rooms where the first and the second lessons take place. Unfortunately, he quickly lost the track of his calculations and decided to count only the timetables that satisfy the following conditions:

1) On the first lesson in classroom i exactly Xi groups must be present.

2) In classroom i no more than Yi groups may be placed.

Help Petya count the number of timetables satisfying all those conditionsю As there can be a lot of such timetables, output modulo 109 + 7.

Input

The first line contains one integer M (1 ≤ M ≤ 100) — the number of classrooms.

The second line contains M space-separated integers — Xi (0 ≤ Xi ≤ 100) the amount of groups present in classroom i during the first lesson.

The third line contains M space-separated integers — Yi (0 ≤ Yi ≤ 100) the maximal amount of groups that can be present in classroom iat the same time.

It is guaranteed that all the Xi ≤ Yi, and that the sum of all the Xi is positive and does not exceed 1000.

Output

In the single line output the answer to the problem modulo 109 + 7.

Examples
input
Copy
3
1 1 1
1 2 3
output
36
input
Copy
3
1 1 1
1 1 1
output
6
Note

In the second sample test the first and the second lessons of each group must take place in the same classroom, that’s why the timetables will only be different in the rearrangement of the classrooms’ numbers for each group, e.g. 3! = 6.


题意:m个教室,第i个教室最多可以容纳yi人上课,初始状态第i个教室有xi人,教室a的人可以移动到b教室(a≤b),问移动后有多少种可能方案,结果模10^9+7

解题思路:dp,首先不考虑人的编号dp[i][j]表示前i个教室分配j个人的方案数,这样获得的答案有很多重复的,最后答案还要除以一些数字


#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <string>  
#include <algorithm>  
#include <map>  
#include <set>
#include <stack>  
#include <queue>  
#include <vector>  
#include <bitset>  
#include <functional>  

using namespace std;

#define LL long long
const int INF = 0x3f3f3f3f;
const LL mod = 1e9 + 7;

LL mul[1000009], inv[1000009];
LL dp[109][10009];
int m, x[109], y[109], sum[109];

void init()
{
	mul[0] = 1;
	for (int i = 1; i < 1000009; i++)
		mul[i] = (mul[i - 1] * i) % mod;
	inv[0] = inv[1] = 1;
	for (int i = 2; i < 1000009; i++)
		inv[i] = (LL)(mod - mod / i)*inv[mod%i] % mod;
	for (int i = 1; i < 1000009; i++)
		inv[i] = (inv[i - 1] * inv[i]) % mod;
}

LL C(int n, int m)
{
	return mul[n] * inv[m] % mod*inv[n - m] % mod;
}

int main()
{
	init();
	while (~scanf("%d", &m))
	{
		sum[0] = 0;
		for (int i = 1; i <= m; i++)
		{
			scanf("%d", &x[i]);
			sum[i] = sum[i - 1] + x[i];
		}
		for (int i = 1; i <= m; i++) scanf("%d", &y[i]);
		memset(dp, 0, sizeof dp);
		dp[0][0] = 1;
		for (int i = 1; i <= m; i++)
			for (int j = 0; j <= sum[i]; j++)
				for (int k = 0; k <= min(j, y[i]); k++)
				{
					dp[i][j] += dp[i - 1][j - k] * C(sum[i] - (j - k), k) % mod;
					dp[i][j] %= mod;
				}
		LL ans = dp[m][sum[m]] * mul[sum[m]] % mod;
		for (int i = 1; i <= m; i++) ans = ans * inv[x[i]] % mod;
		printf("%lld\n", ans);
	}
	return 0;
}
mm个教室,第ii个教室最多可以容纳yiyi人上课,初始状态第ii个教室有xixi人,aa教室的人可以移动到bb教室(ab)(a≤b),问移动后有多少种可能方案,结果模109+7
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值