算法分析
规则后的图形
题目给定的图片是不规则图形,我们可以将它分解成若干个规则图形,因为规则图形可以通过公式直接计算出来,如上图所示,对于某个规则的矩形,长度是a
,宽度是b
,放k
辆车(k <= b <= a
),在长度是a
行中任选k
行进行摆放,共有b
列,第一辆车有b
种摆放方案,第二辆车有b - 1
中摆放方案…,第k
辆车有b - k + 1
种摆放方案,因此一共有CkaAkb种摆放方案
分解图形(按照红线位置划分成两个矩形)
上半部分摆放i
辆车,有 CibAia 种摆放方案
下半部分摆放k - i
辆车,由于上半部分摆放了i
辆车,占用的列对下半部分选择有了一定的影响,即占用的列对于下半部分是不可使用的,因此从d
行中选k - i
行,有a + c - i
列可以进行摆放并摆放k - i
辆车,因此有 Ck−idAk−ia+c−i 种摆放方案
由于上半部分的摆放情况 和 下半部分的摆放情况是相互独立的,因此可以使用乘法原理,上半部分摆放i
辆车,整张图的摆放方案是 CibAiaCk−idAk−ia+c−i
时间复杂度 O(Nlogmod)
N = 2000,mod = 100003
参考文献
算法提高课
Java 代码
import java.util.Scanner;
public class Main {
static int N = 2010, mod = 100003;
static long[] fact = new long[N];
static long[] infact = new long[N];
static long qmi(int a, int k, int p)
{
long res = 1 % p;
long t = a;
while(k != 0)
{
if((k & 1) == 1) res = res * t % mod;
k >>= 1;
t = t * t % mod;
}
return res;
}
static long C(int a, int b)
{
if(a < b) return 0;
return fact[a] * infact[b] % mod * infact[a - b] % mod;
}
static long P(int a, int b)
{
if(a < b) return 0;
return fact[a] * infact[a - b] % mod;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
fact[0] = infact[0] = 1;
for(int i = 1;i < N - 1;i ++)
{
fact[i] = fact[i - 1] * i % mod;
infact[i] = infact[i - 1] * qmi(i, mod - 2, mod) % mod;
}
int a = scan.nextInt();
int b = scan.nextInt();
int c = scan.nextInt();
int d = scan.nextInt();
int k = scan.nextInt();
long res = 0;
for(int i = 0;i <= k;i ++)
{
res = (res + C(b, i) * P(a, i) % mod * C(d, k - i) * P(a + c - i, k - i) % mod) % mod;
}
System.out.println(res);
}
}
赞,我给分成三块想复杂了,但是居然过了
题上有说每辆车都是不一样的吗,,,
您是对CibAia中的Aia有疑问吗,最开始我认为Aia应该是Cia,后来发现想错的点是因为我认为是从a列里面随便选i列即可,不需要顺序,所以是Cia,但是在每一列里面,车究竟在哪一行,是没有考虑到的,所以我们应该在选好了用哪些行以后,针对每一行来看安排在哪一列,若矩阵是3*4的,我们选择了第一行和第二行,然后我们需要在第一行选择一列,有四种选择,在第二行,有三种选择,所以是A24.
也就是说(1,3),(2,4)与(1,4),(2,3)是不同的选择
也就是说在选出列之后还要考虑安排在不同的行上