【Codeforces #178 A】Shaass and Lights

考虑两个灯之间的暗灯,能从左边或右边点亮两种顺序,而最左端或最右端只有一种点亮顺序。

先不考虑点灯顺序,总共有n - m个灯要点亮,对于连续的一段暗灯,他们在总的点灯顺序中的是等价的,于是问题就可以抽象成有重复元素的组合数:

$ C = \frac{ (n - m)! }{ \prod_{i = 1}^{k} \, x_{i} ! }  $ 。

在考虑一段连续的暗灯内部的点灯顺序,只要让答案乘上 $ 2 ^ {len - 1} $ 即可。

技巧&套路:

  • 组合数应用的模型,组合数的运用
 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 typedef long long LL;
 5 const int N = 1005, MOD = 1e9 + 7;
 6 
 7 int n, m, a[N], d[N], pw2[N], fac[N];
 8 
 9 int Pow(int x, int b, int re = 1) {
10     for (; b; b >>= 1, x = (LL) x * x % MOD) if (b & 1) re = (LL) re * x % MOD;
11     return re;
12 }
13 
14 int main() {
15     scanf("%d%d", &n, &m);
16     pw2[0] = fac[0] = 1;
17     for (int i = 1; i <= m; ++i) {
18         scanf("%d", &a[i]);
19     }
20     for (int i = 1; i <= n; ++i) {
21         pw2[i] = pw2[i - 1] * 2 % MOD;
22         fac[i] = (LL) fac[i - 1] * i % MOD;
23     }
24     std::sort(a + 1, a + 1 + m);
25     
26     int ans = fac[n - m];
27     for (int i = 1; i < m; ++i) {
28         int d = a[i + 1] - a[i] - 1;
29         if (d == 0) continue;
30         ans = (LL) ans * Pow(fac[d], MOD - 2) % MOD;
31         ans = (LL) ans * pw2[d - 1] % MOD;
32     }
33     if (a[1] > 1) ans = (LL) ans * Pow(fac[a[1] - 1], MOD - 2) % MOD;
34     if (a[m] < n) ans = (LL) ans * Pow(fac[n - a[m]], MOD - 2) % MOD;
35     printf("%d\n", ans);
36     
37     return 0;
38 }
View Code

猜你喜欢

转载自www.cnblogs.com/Dance-Of-Faith/p/9296652.html