题目大意:
题目链接:https://ac.nowcoder.com/acm/contest/1085/J
有一个含有
n
n
n个数字的序列,每个数的大小是不超过
1000
1000
1000的正整数,同时这个序列是个单调不增序列。但是很不幸的是,序列在保存过程中有些数字丢失了,请你根据上述条件,计算出有多少种不同的序列满足上述条件,答案对
1000000007
1000000007
1000000007取模。(具体可以看样例)
思路:
首先题目要求一个单调不增序列,套路性的把位置
i
i
i上的数字加上
n
−
i
+
1
n-i+1
n−i+1。这样就转变成了一个单调递减序列。
那么对于位置
i
,
j
i,j
i,j的两个已知数字,如果
(
i
,
j
)
(i,j)
(i,j)中全部是未知数字,那么显然我们就需要在¥
a
[
i
]
,
a
[
i
+
1
]
.
.
.
a
[
j
−
1
]
,
a
[
j
]
a[i],a[i+1]...a[j-1],a[j]
a[i],a[i+1]...a[j−1],a[j]共
a
[
i
]
−
a
[
j
]
−
1
a[i]-a[j]-1
a[i]−a[j]−1个数字中选出
j
−
i
−
1
j-i-1
j−i−1个数字,满足这些数字排序后单调递减。
显然这就是
C
a
[
i
]
−
a
[
j
]
−
1
j
−
i
−
1
C_{a[i]-a[j]-1}^{j-i-1}
Ca[i]−a[j]−1j−i−1。因为组合是满足互不相同的。
为了方便,就在
a
a
a中加入
n
,
0
n,0
n,0两个元素,注意
n
n
n和
0
0
0都是要加上
n
−
i
+
1
n-i+1
n−i+1的。
代码:
#include <cstdio>
using namespace std;
typedef long long ll;
const int N=1000010,MOD=1000000007;
ll a[N],last,f[N*2],ans;
int n;
ll power(ll x,ll k)
{
ll s=1;
for (;k;k>>=1,x=x*x%MOD)
if (k&1) s=s*x%MOD;
return s;
}
ll C(ll x,ll y)
{
if (x<y) return 0;
ll inv=power(f[y]*f[x-y]%MOD,MOD-2);
return f[x]*inv%MOD;
}
int main()
{
f[0]=1;
for (int i=1;i<=N+2000;i++)
f[i]=f[i-1]*i%MOD;
scanf("%d",&n); n+=2;
a[1]=1000+n;
for (int i=2;i<n;i++)
{
scanf("%d",&a[i]);
if (a[i]) a[i]+=(n-i+1);
}
a[n]=2;
ans=1;
for (int i=1;i<=n;i++)
if (a[i])
{
if (last) ans=ans*C(a[last]-a[i]-1,i-last-1)%MOD;
last=i;
}
printf("%lld",ans);
return 0;
}