「百錢買百雞」是中國古典數學問題,也是C語言初學者練習循環嵌套、條件判斷、整數運算的經典案例。本文展示從暴力三重循環到數學優化二重循環的演進過程。
x + y + z = 100 // 總數
5x + 3y + z/3 = 100 // 總價
x,y,z ≥ 0 且為整數, z % 3 == 0
#include
void main(void) {
int x, y, z; // 公、母、小
for (x = 1; x < 21; x++) { // 公雞最多100/5=20
for (y = 1; y < 34; y++) { // 母雞最多100/3≈33
for (z = 1; z < 100; z += 3) { // 小雞步長3(整數價)
if (5*x + 3*y + z/3 == 100 && x + y + z == 100) {
printf("公雞%d只 母雞%d只 小雞%d只\n", x, y, z);
}
}
}
}
getchar();
}
z += 3利用「小雞數必為3的倍數」剪枝由x + y + z = 100得z = 100 - x - y,代入價格方程:
5x + 3y + (100 - x - y)/3 = 100
→ 15x + 9y + 100 - x - y = 300
→ 14x + 8y = 200
→ 7x + 4y = 100
只需雙重循環驗證7x + 4y == 100且z = 100-x-y為3的倍數:
#include
void main(void) {
int x, y;
for (x = 1; x < 21; x++) {
for (y = 1; y < 34; y++) {
if (7*x + 4*y == 100 && (100 - x - y) % 3 == 0) {
int z = 100 - x - y;
printf("公雞%d只 母雞%d只 小雞%d只\n", x, y, z);
}
}
}
getchar();
}
由7x + 4y = 100,對x求解y = (100 - 7x)/4:
#include
int main() {
for (int x = 1; x <= 20; x++) {
int remainder = 100 - 7*x;
if (remainder % 4 == 0) {
int y = remainder / 4;
int z = 100 - x - y;
if (z >= 0 && z % 3 == 0) {
printf("公雞%d只 母雞%d只 小雞%d只\n", x, y, z);
}
}
}
return 0;
}
x(1~20),20次循環,O(1)級效率| 公雞 | 母雞 | 小雞 | 驗算 |
|---|---|---|---|
| 4 | 18 | 78 | 4×5+18×3+78/3=20+54+26=100 |
| 8 | 11 | 81 | 40+33+27=100 |
| 12 | 4 | 84 | 60+12+28=100 |
| 解法 | 時間複雜度 | 實際循環次數 | 核心思想 |
|---|---|---|---|
| 三重循環 | O(N³) | ~21,780 | 暴力枚舉 |
| 二重循環 | O(N²) | 660 | 消去一變量 |
| 單循環 | O(N) | 20 | 代數求解 |
| 數學公式 | O(1) | 1 | 線性不定方程通解 |