1 /*
2 Source :hihocoder编程练习73
3 Problem :一个长度为n的串,由若干段1-a[i](假设有Y段)的序列组成,现在中间缺了K个数,问能够还原出来的方案数,需要保证还原出来的子串的个数最少,即最小Y
4 Solution :1.通过分析剩余的序列,我们可以知道原来最少的时候Y是多少,即看原来的序列有多少单调递增的子段。
5 2.进行有解的判断,假设已知序列段中每段的最大值是b[i] i=1..Y,如果sum(b[i]) > N,则说明无解,这是序列的长度一定已经超过n了。
6 3.方案数求解,假设每段序列的最大值为x[i],有sum(x[i])=n,且需要满足x[i]>=b[i],令y[i]=x[i]-b[i]>=0
7 问题就转化为求sum(y[i])=n-sum(b[i])的解的个数,这是个经典的问题,用隔板法方案数为C(R+Y-1,Y-1), R=n-sum(b[i]).
8 Date :2018-08-19-11.57
9 */
10
11 #include <bits/stdc++.h>
12 using namespace std;
13
14 typedef long long LL;
15 const int MAXN = 100005;
16 const LL MOD7 = 1e9+7;
17
18
19 LL Pow(LL a, LL b)
20 {
21 LL res=1LL;
22 LL ans=a%MOD7;
23 while (b)
24 {
25 if (b&1) res=res*ans%MOD7;
26 ans=ans*ans%MOD7;
27 b>>=1;
28 }
29 return res;
30 }
31
32 int a[MAXN];
33 int N, K, M;
34 int m;
35 LL R;
36 LL Y;
37
38
39 LL C(LL n, LL r)
40 {
41 LL ans=1LL;
42 for (int i=1;i<=r;++i)
43 {
44 ans = ans * (n-i+1) % MOD7;
45 ans = ans * Pow(i, MOD7-2) % MOD7;
46 }
47 return ans;
48 }
49
50 void work()
51 {
52 LL ans=1LL;
53 ans = C((LL)R+Y-1, (LL)min(Y-1, R));
54 printf("%lld\n",ans);
55 }
56
57 int main()
58 {
59 #ifndef ONLINE_JUDGE
60 freopen("test.txt","r",stdin);
61 #endif // ONLINE_JUDGE
62 scanf("%d%d",&N,&K);
63 m=N-K;
64 for (int i=1;i<=m;++i)
65 {
66 scanf("%d",&a[i]);
67 }
68 a[m+1]=0;
69 R=N;
70 Y=0;
71 for (int i=1;i<=m;++i)
72 {
73 if (a[i]>=a[i+1])
74 {
75 ++Y;
76 R-=a[i];
77 }
78 }
79 if (R<0)
80 {
81 printf("No\n");
82 return 0;
83 }
84 work();
85 return 0;
86 }