百钱百鸡问题方案数的 $O(n)$ 及 $O(1)$ 解法

前置知识

解决本题需要的前置知识是 二元一次方程组求解

但是就算还没有学到二元一次方程求解应该看一下下面的解释也能够看懂哒 (^_−)☆

问题描述

一只公鸡 \(5\) 元钱,一只母鸡 \(3\) 元钱,而一元钱能买 \(3\) 只小鸡。现有 \(n\) 元钱,想买 \(n\) 只鸡,问可买公鸡、母鸡、小鸡各几只,输出方案数(\(n \le 5 \cdot 10^6\))。

问题分析

首先,假设公鸡有 \(x\) 只,母鸡有 \(y\) 只,小鸡有 \(z\) 只,可列方程组如下:

\[\begin{cases} x+y+z=n \\ 5x+3y+\frac{z}{3}=n \end{cases} \]

不妨设攻击数量 \(x\) 已知,可以推出母鸡数量和小鸡数量关于 \(x\) 的公示,推导过程如下:

\[\begin{cases} y + z = n - x \\ 3y + \frac{z}{3} = n - 5x \end{cases} \]

\[\begin{cases} y + z = n - x \\ 9y + z = 3n-15x \end{cases} \]

将上述两个式子相减可以消去 \(z\),得到 \(y\) 关于 \(x\) 的式子:

\[8y = 2n-14x \]

\[\Rightarrow \]

\[y = \frac{n - 7x}{4} \]

再将 \(y\) 的值代入方程 \(y + z = n - x\) 得:

\[z = \frac{3}{4} (n + x) \]

\(O(n)\) 解法

此时可以发现一个很明显的 \(O(n)\) 的算法,就是从 \(1\)\(n-2\) 枚举 \(x\),然后判断 \(y = \frac{n-7x}{4}\) 是不是一个整数且大于 \(0\)\(x = \frac{3}{4}(n+x)\) 是否是一个整数即可。

因为已经保证 \(x+y+z = n\),且 \(x\)\(z\) 都是正整数,所以只要保证 \(y \gt 0\) 就是一个合法的解。

示例程序:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n, cnt = 0;
    cin >> n;
    for (int x = 1; x <= n-2; x++) {
        if ((n - 7 * x) % 4 || (n + x) % 4) continue;
        int y = (n - 7 * x) / 4,
            z = 3 * (n + x) / 4;
        if (y <= 0)     // // 随着 x 的增加,y 是减小的,
            break;      // 当 y <= 0 时接下来也不再有解,就可以提前结束了
        cout << x << " " << y << " " << z << endl;  // 输出对应的方案数
        cnt++;  // 方案数 +1
    }
    cout << "总方案数 = " << cnt << endl;
    return 0;
}

\(O(1)\) 解法

也有 \(O(1)\) 的解法可以求出总的方案数。

根据上面的推导:

\[\begin{cases} y = \frac{n - 7x}{4} \\ z = \frac{3}{4} (n + x) \end{cases} \]

\(y\) 也可以表示成

\[y = \frac{n + x - 8x}{4} = \frac{n+x}{4} - 2x \]

可以发现,当 \(n + x\)\(4\) 的倍数时 \(y\)\(z\) 都是整数。

又因为需要 \(y \gt 0\),即 \(n - 7x \gt 0\),即 \(x \lt \frac{n}{7}\),考虑到实际运算时都是整数运算,所以不等式可以写成

\[x \le \lceil \frac{n}{7} \rceil - 1 \]

对应的 C++ 表达式为 x <= (n + 6) / 7 - 1

m = (n + 6) / 7 - 1,则 \(x \le m\)

然后分情况讨论:

  • n % 4 == 0 时,需要 x % 4 == 0,满足条件的公鸡的数量为 m / 4
  • n % 4 == 1 时,需要 x % 4 == 3,满足条件的公鸡的数量为 (m + 1) / 4
  • n % 4 == 2 时,需要 x % 4 == 2,满足条件的公鸡的数量为 (m + 2) / 4
  • n % 4 == 3 时,需要 x % 4 == 1,满足条件的公鸡的数量为 (m + 3) / 4

归纳可知:满足条件的方案数为 (m + n % 4) / 4 种。

示例程序:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;
    int m = (n + 6) / 7 - 1;
    cout << (m + n % 4) / 4 << endl;
    return 0;
}
posted @ 2023-01-04 23:48  quanjun  阅读(180)  评论(0编辑  收藏  举报