题目描述
有下面这样的一个网格棋盘,a,b,c,d 表示了对应边长度,也就是对应格子数。
当 a=b=c=d=2 时,对应下面这样一个棋盘:
要在这个棋盘上放 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个棋子。
一个长为n,宽为m的网格,放k个棋子。
首
先
我
们
可
以
从
m
行
中
选
择
k
行
,
结
果
为
C
m
k
。
首先我们可以从m行中选择k行,结果为C_m^k。
首先我们可以从m行中选择k行,结果为Cmk。
然
后
每
一
行
的
选
择
数
有
n
∗
(
n
−
1
)
∗
(
n
−
2
)
∗
…
…
∗
(
n
−
k
+
1
)
,
即
A
m
k
。
然后每一行的选择数有n*(n-1)*(n-2)*……*(n-k+1),即A_m^k。
然后每一行的选择数有n∗(n−1)∗(n−2)∗……∗(n−k+1),即Amk。
最
终
的
答
案
即
为
:
C
m
k
∗
A
m
k
最终的答案即为:C_m^k*A_m^k
最终的答案即为:Cmk∗Amk
有 了 这 个 结 论 , 我 们 再 来 看 这 道 题 , 其 实 就 是 一 个 大 的 长 方 形 上 加 了 一 个 小 的 长 方 形 。 有了这个结论,我们再来看这道题,其实就是一个大的长方形上加了一个小的长方形。 有了这个结论,我们再来看这道题,其实就是一个大的长方形上加了一个小的长方形。
我
们
可
以
先
将
k
个
棋
子
分
到
上
下
两
个
长
方
形
中
,
假
设
上
面
的
长
方
形
中
分
配
i
个
棋
子
,
而
下
面
的
长
方
形
则
分
配
k
−
i
个
棋
子
。
我们可以先将k个棋子分到上下两个长方形中,假设上面的长方形中分配i个棋子,而下面的长方形则分配k-i个棋子。
我们可以先将k个棋子分到上下两个长方形中,假设上面的长方形中分配i个棋子,而下面的长方形则分配k−i个棋子。
我
们
先
来
算
小
的
长
方
形
,
直
接
带
入
我
们
推
出
的
表
达
式
即
可
,
答
案
即
为
:
C
b
i
∗
A
a
i
。
我们先来算小的长方形,直接带入我们推出的表达式即可,答案即为:C_b^i*A_a^i。
我们先来算小的长方形,直接带入我们推出的表达式即可,答案即为:Cbi∗Aai。
然
后
我
们
来
算
大
的
长
方
形
,
首
先
在
d
行
中
选
择
k
−
i
行
,
结
果
为
C
d
k
−
i
。
然后我们来算大的长方形,首先在d行中选择k-i行,结果为C_d^{k-i}。
然后我们来算大的长方形,首先在d行中选择k−i行,结果为Cdk−i。
然
后
每
一
行
的
选
择
数
有
(
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+c−i)∗(a+c−i−1)∗……∗(a+c−k+1),即Aa+c−ik−i。
下
长
方
形
的
方
案
数
即
为
:
C
d
k
−
i
∗
A
a
+
c
−
i
k
−
i
。
下长方形的方案数即为:C_d^{k-i}*A_{a+c-i}^{k-i}。
下长方形的方案数即为:Cdk−i∗Aa+c−ik−i。
因 此 , 最 终 的 答 案 为 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}。 因此,最终的答案为Cbi∗Aai∗Cdk−i∗Aa+c−ik−i。
最 后 枚 举 所 有 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;
}