UVa 580 Critical Mass (递推 & 计数原理)

题目

题目大意

有一些装有铀(用(U)表示)和铅(用(L)表示)的盒子, 数量均足够多。要求把(n)((n ≤ 30))个盒子放成一行, 但至少有(3)(U)放在一起, 有多少种放法? 例如, (n = 4, 5, 30)时答案分别为(3, 8)(974791728)

题解

设答案为(f(n)), 根据(3)(U)的位置分类。假定是(i), (i + 1), (i + 2)这三个盒子, 则前(i - 1)个盒子不能有(3)(U)放在一起, 而(i - 2)(i - 1)仍然有可能与(i)(i + 1)组成(3)(U), 因此保证(i - 1)(L)。设(n)个盒子没有(3)(U)放在一起的方案数为(g(n) = 2^n-f(n)), 则前(i - 2)个盒子的方案有(g(i - 2))种。根据加法原理和乘法原理, 得到(f(n) = 2^{n - 3} + Sigma_{i = 2}^{n - 2}g(i - 2)2^{n - i - 2})

代码

#include <cstdio>
long long f[40], g[40] = {1, 2, 4};
int n;
int main(int argc, char const *argv[]) {
  for (register int i(3); i <= 30; ++i) {
    f[i] = 1 << (i - 3);
    for (register int j(2); j < i - 1; ++j) {
      f[i] += g[j - 2] * (1 << (i - j - 2));
    }
    g[i] = (1 << i) - f[i];
  }
  while (~scanf("%d", &n) && n) {
    printf("%lld
", f[n]);
  }
  return 0;
}
原文地址:https://www.cnblogs.com/forth/p/9720757.html