hihocoder编程练习赛73 A 地铁站

 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 }

猜你喜欢

转载自www.cnblogs.com/LeeSongt/p/9502231.html
今日推荐