maoge有N(2<=N<=1000)块砖,要搭一个塔,要求:如果砖A在砖B上面,那么A不能比B的长度-D(1<=D<=n)要长。问有几种方法,输出 答案 mod 1000000007的值。
注意,塔的高度不能为0。
【输入格式】
第一行: N,D 第二行: N个数,表示每块砖的长度,保证为正整数且小于等于10000。
【输出格式】
方案数,输出要mod 1000000007。
【样例输入】
4 1
1 2 3 100
【样例输出】
15
本来想1层,两层,3层之类的,但代码有点写不出来
差一点就想偷懒直接用2^N -1来当做答案了~~不过看了看题目,有个 - D阀值,所以不行。
除非指定了这个塔是多少层的,否则是很难用普通的循环嵌套搞定的。
因为只要求总共的方案数就可以不必打印出每种方案,所以想了一个用表格逆推的方法来求解(这类问题在不想用递归的时候我总是这么干)
首先把所有的砖按照尺寸从小到大的顺序整理一下。排序算法有很多,时间耗费从O(N * Log(2,N))到O(N^2)不等。
现在假设有广义递增数列A={a[1], a[2], ..., a[N])满足a[i]<=a[i+1],我们来看一下怎么排这个塔。
我们先给每一种排法一个唯一号。譬如,我们取了第13,第2,第97块砖构成一个塔,我们就把它记录为{2,13,97}方案。显然不同的取法这样的方案编号是不一样的。我们称方案中所取的最小的砖的编号为方案头,上面的例子中的方案就是以a[2]作为方案头的。做这些约定是为了后面讨论方便。
先只取第N块砖a[N],这显然是可以构成一个单层塔的。记录在案。
接着我们看a[N-1]。单取a[N-1]显然是一种可行的方案。然后如果a[N-1]和a[N]的差距足够大( >= D),那么所有以a[N]开头的方案都可以附上a[N-1]的前缀变成一种新的方案(当然喽,如果它们挨得太紧,就不能作为可行的方案)。这样一来,我们把第N-1块砖也整理好了。
现在开始用一下数学归纳法里的递推假设。
假设我已经整理好了以a[N],a[N-1],...,a[i+1]作为方案头的方案数量,现在我们来讨论一下以a[i]作为头的方案有多少种。
单取a[i]显然是一种合理的方案。
然后呢,如果a[i+1]和a[i]的差距足够大( >= D),我们自然可以把所有以a[i+1]作为方案头的方案增加a[i]的前缀变成新的方案。
如果a[i+1]和a[i]不幸挨得太近,我们就只好退而求其次,看看a[i+2]和a[i]的差距了。
假设我们经过千辛万苦,找到了一个最小的j,j>i,恰好满足a[j]-a[i]>=D,而a[j-1]-a[i]<D,则显然的所有以a[i+1],...,a[j-1]开头的方案都不能增加a[i]的前缀,而所有的以a[j]开头的方案都可以增加a[i]的前缀。
既然a[j]都可以增加a[i]作为前缀了,那么a[j+1]自然也可以,依次类推直到以a[N]为方案头的每一个方案都可以增加a[i]作为前缀。
这样一来,我们借助之前已经整理好的以a[i+1]~a[N]作为方案头的方案数量,成功的将以a[i]作为方案头的方案数量给“算”出来了。
一路往前,当我们把a[1]的方案数量算出来之后,求一个和就得到了总的数量了。
看一下整个过程,我们需要对数量A={a[1],...,a[N]}进行如下一些预处理
先整理出一个Next_A={next_a[1],next_a[2],...next_a[N]}用来存放以a[i]作为方案头的下一个勉强满足a[j]-a[i] >= D的序列号 j ,这样当处理a[i]的时候可以很快的查到a[j]的位置。(这个Next_A的列表,可以用指针追逐的方法在O(N)时间内完成)
然后准备一个数组来Sum={sum[1],sum[2],...sum[N]}={0,...,0}来存放方案数量。
这里的sum[i]表示以a[i]作为方案头的方案数量
然后,整个计算过程是:
//1. 一路倒推到a[0]的方案总数。
for (i=N;i>=1; i--) {
sum[i]=1;
if (next_a[i] >i and next_a[i]<=N) {
for (j=next_a[i], j<=N; j++) {
sum[i] = sum[i]+sum(next_a[j]);
}
}
}
//汇总以各个a[i]为方案头的方案数量
result = 0;
for (i=1; i<=N; i++) {
result = result+ sum[i]
}
这个算法的复杂度是O(N^2),主要是那个求sum[j],...sum[N]的汇总慢。
通过增加一个新的数组GlobalSum={g_sum[1], g_sum[2],..., g_sum[N]},其中g_sum[i]= sum[i]+sum[i+1]+...+sum[N]可以将时间复杂度降低到O(N)。