题解:洛谷 P2907 Roads Around The Farm

【题目来源】

洛谷:P2907 [USACO08OPEN] Roads Around The Farm S - 洛谷

【题目描述】

Farmer John 的奶牛对探索农场周围的领地产生了兴趣。最初,所有 \(N\) 头奶牛(\(1 \leq N \leq 10^9\))以一个大群体的形式开始沿着一条道路旅行。当遇到岔路时,群体有时会选择分成两个较小的(非空)群体,每个群体沿着一条道路继续前进。当其中一个群体到达另一个岔路时,它可能会再次分裂,依此类推。

奶牛们设计了一种特殊的分裂方式:如果它们可以分裂成两个群体,使得群体的大小正好相差 \(K\)\(1 \leq K \leq 1000\)),那么它们就会以这种方式分裂;否则,它们就停止探索,开始安静地吃草。

假设总是会有新的岔路,计算最终安静吃草的奶牛群的数量。

【输入】

两个空格分隔的整数,\(N\)\(K\)

【输出】

一个整数,表示安静吃草的奶牛群的数量。

【输入样例】

6 2

【输出样例 】

3

【核心思想】

  1. 问题分析:给定 \(N\) 头奶牛和差值 \(K\),一个大小为 \(n\) 的群体若能分裂为两个非空群体且大小相差恰好 \(K\)(即 \(a - b = K\)\(a + b = n\)),则继续分裂;否则停止。求最终停止的群体数量。这是一个递归分治问题,关键在于发现分裂条件可解出 \(a = (n+K)/2\)\(b = (n-K)/2\),要求 \(n > K\)\(n-K\) 为偶数。

  2. 算法选择

    • 递归模拟:直接按照分裂规则递归计算,每个群体要么分裂为两个继续递归,要么计数为 \(1\)
    • 数学判定:分裂条件为 \((n-K) \% 2 = 0\)\(n > K\),此时 \(a = (n+K)/2\)\(b = (n-K)/2\)
  3. 关键步骤

    • 读取输入\(N, K\)
    • 递归函数 calc(n, k)
      • \((n-K) \% 2 = 0\)\(n > K\):可分裂
        • \(a = (n+K)/2\)\(b = (n-K)/2\)
        • 返回 calc(a, k) + calc(b, k)
      • 否则:不可分裂,返回 \(1\)
    • 输出 calc(N, K)
  4. 时间/空间复杂度

    • 时间复杂度:\(O(\log N)\),每次分裂规模大致减半
    • 空间复杂度:\(O(\log N)\),递归栈深度
  5. 递归分治的核心思想

    • 分裂方程求解:由 \(a + b = n\)\(a - b = K\) 联立得 \(a = (n+K)/2\)\(b = (n-K)/2\)。要求 \(a, b\) 为正整数,即 \(n > K\)\(n-K\) 为偶数
    • 二叉树式分裂:每次分裂形成两个子问题,递归求解后累加叶子节点数(不可再分的群体数)
    • 终止条件:当群体大小无法表示为两个相差 \(K\) 的正整数之和时,该群体成为叶子节点
    • 适用于"规则递归分裂 + 计数叶子节点"类问题,核心是正确表达分裂条件和终止条件

【解题思路】

【算法标签】

入门 #递归

【代码详解】

#include <bits/stdc++.h>
using namespace std;
int n, k, ans;
int calc(int n, int k)  // 定义递归函数
{
    int a, b, ans=0;  // 定义局部变量a和b,以及群数,初始为0
    if ((n-k)%2==0 && n>k) {  // 如果b为整数(则a也是整数),且当前这个数n大于k(即可分裂)
        a = (n+k)/2;  // 计算分裂a、b两组的值
        b = (n-k)/2;
        ans += calc(a, k);  // 使用a和k继续递归查找,从最后一层逐级加上ans的值,即有多少无法分裂的数,就加多少个1
        ans += calc(b, k);  // 使用b和k继续递归查找
    } else {  // 无法再按分裂方式分裂
        ans = 1;  // 则群数为1
    }
    return ans;  // 返回这个群数
}
int main()
{
    cin >> n >> k;  // 输入n和k
    ans = calc(n, k);  // 使用递归方式计算
    cout << ans << endl;  // 打印群数
    return 0;
}

【运行结果】

6 2
3
posted @ 2026-08-28 15:55  团爸讲算法  阅读(2)  评论(0)    收藏  举报