1309. 车的放置(组合数学)

题目描述

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

输入格式

共一行,五个非负整数 a,b,c,d,k。

输出格式

包括一个正整数,为答案 mod100003 后的结果。

数据范围

0≤a,b,c,d,k≤1000,
保证至少有一种可行方案。

输入样例
2 2 2 2 2
输出样例
38

题目分析

既 然 这 种 不 规 则 图 形 不 好 计 算 , 那 我 们 可 以 先 算 一 下 普 通 正 方 形 的 解 。 既然这种不规则图形不好计算,那我们可以先算一下普通正方形的解。 请添加图片描述

一 个 长 为 n , 宽 为 m 的 网 格 , 放 k 个 棋 子 。 一个长为n,宽为m的网格,放k个棋子。 nmk
首 先 我 们 可 以 从 m 行 中 选 择 k 行 , 结 果 为 C m k 。 首先我们可以从m行中选择k行,结果为C_m^k。 mkCmk
然 后 每 一 行 的 选 择 数 有 n ∗ ( n − 1 ) ∗ ( n − 2 ) ∗ … … ∗ ( n − k + 1 ) , 即 A m k 。 然后每一行的选择数有n*(n-1)*(n-2)*……*(n-k+1),即A_m^k。 n(n1)(n2)(nk+1)Amk
最 终 的 答 案 即 为 : C m k ∗ A m k 最终的答案即为:C_m^k*A_m^k CmkAmk

有 了 这 个 结 论 , 我 们 再 来 看 这 道 题 , 其 实 就 是 一 个 大 的 长 方 形 上 加 了 一 个 小 的 长 方 形 。 有了这个结论,我们再来看这道题,其实就是一个大的长方形上加了一个小的长方形。

我 们 可 以 先 将 k 个 棋 子 分 到 上 下 两 个 长 方 形 中 , 假 设 上 面 的 长 方 形 中 分 配 i 个 棋 子 , 而 下 面 的 长 方 形 则 分 配 k − i 个 棋 子 。 我们可以先将k个棋子分到上下两个长方形中,假设上面的长方形中分配i个棋子,而下面的长方形则分配k-i个棋子。 kiki
我 们 先 来 算 小 的 长 方 形 , 直 接 带 入 我 们 推 出 的 表 达 式 即 可 , 答 案 即 为 : C b i ∗ A a i 。 我们先来算小的长方形,直接带入我们推出的表达式即可,答案即为:C_b^i*A_a^i。 CbiAai

然 后 我 们 来 算 大 的 长 方 形 , 首 先 在 d 行 中 选 择 k − i 行 , 结 果 为 C d k − i 。 然后我们来算大的长方形,首先在d行中选择k-i行,结果为C_d^{k-i}。 dkiCdki
然 后 每 一 行 的 选 择 数 有 ( a + c − i ) ∗ ( a + c − i − 1 ) ∗ … … ∗ ( a + c − k + 1 ) , 即 A a + c − i k − i 。 然后每一行的选择数有(a+c-i)*(a+c-i-1)*……*(a+c-k+1),即A_{a+c-i}^{k-i}。 (a+ci)(a+ci1)(a+ck+1)Aa+ciki
下 长 方 形 的 方 案 数 即 为 : C d k − i ∗ A a + c − i k − i 。 下长方形的方案数即为:C_d^{k-i}*A_{a+c-i}^{k-i}。 CdkiAa+ciki

因 此 , 最 终 的 答 案 为 C b i ∗ A a i ∗ C d k − i ∗ A a + c − i k − i 。 因此,最终的答案为C_b^i*A_a^i*C_d^{k-i}*A_{a+c-i}^{k-i}。 CbiAaiCdkiAa+ciki

最 后 枚 举 所 有 i , 求 出 所 有 情 况 之 和 即 可 。 最后枚举所有i,求出所有情况之和即可。 i

补 充 : 为 什 么 要 先 算 上 面 小 长 方 形 ? 补充:为什么要先算上面小长方形?
因 为 上 面 的 小 长 方 形 对 下 面 长 方 形 的 影 响 是 固 定 的 , 它 一 定 会 占 用 i 列 。 因为上面的小长方形对下面长方形的影响是固定的,它一定会占用i列。 i
而 下 面 长 方 形 对 上 面 的 影 响 是 不 固 定 的 , 我 们 不 确 定 下 面 棋 子 占 用 的 列 是 否 会 影 响 到 上 面 , 因 此 不 好 计 算 。 而下面长方形对上面的影响是不固定的,我们不确定下面棋子占用的列是否会影响到上面,因此不好计算。

代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#define LL long long
#define ULL unsigned long long
#define PII pair<int,int>
#define x first
#define y second
using namespace std;
const int N=2e3+5,mod=100003;
int fact[N],infact[N];
int qmi(int a,int k)				//快速幂
{
    int res=1;
    while(k)
    {
        if(k&1) res=(LL)res*a%mod;
        a=(LL)a*a%mod;
        k>>=1;
    }
    return res;
}
void init()						//预处理出i的阶乘和对应的逆元(因为mod为素数,因此可以用快速幂求逆元)
{
    fact[0]=infact[0]=1;
    for(int i=1;i<N;i++)
    {
        fact[i]=(LL)fact[i-1]*i%mod;
        infact[i]=qmi(fact[i],mod-2);
    }
}
int C(int a,int b)				//求C(a,b)的函数
{
    if(b>a) return 0;
    return (LL)fact[a]*infact[a-b]*infact[b]%mod;
}
int A(int a,int b)				//求A(a,b)的函数
{
    if(b>a) return 0;
    return (LL)fact[a]*infact[a-b]%mod;
}
int main()
{
    init();
    int a,b,c,d,k;
    cin>>a>>b>>c>>d>>k;
    int ans=0;
    for(int i=0;i<=k;i++)			//枚举i的所有情况,求和即可
        ans=(ans+(LL)C(b,i)*A(a,i)%mod*C(d,k-i)*A(a+c-i,k-i))%mod;
    
    cout<<ans<<endl;
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lwz_159

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值