【ACWing】1309. 车的放置

题目地址:

https://www.acwing.com/problem/content/description/1311/

有下面这样的一个网格棋盘, a , b , c , d a,b,c,d a,b,c,d表示了对应边长度,也就是对应格子数。
在这里插入图片描述
a = b = c = d = 2 a=b=c=d=2 a=b=c=d=2时,对应下面这样一个棋盘:
2.png
要在这个棋盘上放 k k k个相互不攻击的车,也就是这 k k k个车没有两个车在同一行,也没有两个车在同一列,问有多少种方案。只需要输出答案 m o d    100003 \mod100003 mod100003后的结果。

输入格式:
共一行,五个非负整数 a , b , c , d , k a,b,c,d,k a,b,c,d,k

输出格式:
包括一个正整数,为答案 m o d    100003 \mod100003 mod100003后的结果。

数据范围:
0 ≤ a , b , c , d , k ≤ 1000 0≤a,b,c,d,k≤1000 0a,b,c,d,k1000,保证至少有一种可行方案。

所有方案可以按照上面 b b b行放多少个来分类,如果上面 b b b行放 x x x个,下面 d d d行就只能放 k − x k-x kx个。对于不同的 x x x方案互不交叉,从而可以用加法原理。我可以分步骤,考虑上面放 x x x个的方案,可以先选 x x x个不同行,方案数为 C ( b , x ) C(b,x) C(b,x),选定行的情况下,它们的列是排列数 A ( a , x ) A(a, x) A(a,x);考虑完上面接着考虑下面,同样先选行,则有 C ( d , k − x ) C(d, k-x) C(d,kx)个方案,选定好行之后,只有 a + c − x a+c-x a+cx个列可供选择,从而方案数为 A ( a + c − x , k − x ) A(a+c-x,k-x) A(a+cx,kx)。综上,方案数为 ∑ x = 0 b C ( b , x ) A ( a , x ) C ( d , k − x ) A ( a + c − x , k − x ) \sum_{x=0}^{b}C(b,x)A(a,x)C(d,k-x)A(a+c-x,k-x) x=0bC(b,x)A(a,x)C(d,kx)A(a+cx,kx)组合数和排列数可以预处理出来。组合数可以利用 C ( n , k ) = C ( n − 1 , k − 1 ) + C ( n − 1 , k ) C(n,k)=C(n-1,k-1)+C(n-1,k) C(n,k)=C(n1,k1)+C(n1,k)递推,排列数可以利用组合数求: A ( n , k ) = k ! C ( n , k ) A(n,k)=k!C(n,k) A(n,k)=k!C(n,k)。代码如下:

#include <iostream>
using namespace std;
using ll = long long;

const int N = 2010, MOD = 100003;
int a, b, c, d, k;
ll C[N][N], A[N][N];

int main() {
  scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
  for (int i = 0; i <= max(max(b, d), a + c); i++)
    for (int j = 0, fact = 1; j <= i; j++) {
      if (!j) C[i][j] = 1;
      else {
        C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
        fact = fact * j % MOD;
      }
      A[i][j] = C[i][j] * fact % MOD;
    }

  int res = 0;
  for (int x = 0; x <= b; x++)
    res = (res + C[b][x] * A[a][x] % MOD * C[d][k - x] % MOD *
                     A[a + c - x][k - x] % MOD) % MOD;
  printf("%d\n", res);
}

时间复杂度 O ( b ( max ⁡ { b , d , a + c } ) 2 ) O(b(\max\{b,d,a+c\})^2) O(b(max{b,d,a+c})2),空间 O ( ( max ⁡ { b , d , a + c } ) 2 ) O((\max\{b,d,a+c\})^2) O((max{b,d,a+c})2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值