欢迎光临
我们一直在努力

UVa 799 Safari Holiday

题目描述

有 nnn 个人参加游猎假期,活动安排需满足以下规则:

  • 每天所有人分成若干组,每组人数完全相同,记为 kkk ,且 kkk 不得超过组织者规定的最大值 kmaxkmaxkmax 。
  • 每天每个人所在的组,其组内其他 k−1k-1k−1 个人必须与之前任何一天的组员都不同(即任意两人至多同组一次)。
  • 游猎结束时,任意两个人都必须曾在某一天同组过(即任意两人至少同组一次)。
  • 给定 nnn 和 kmaxkmaxkmax ,要求找出满足条件的 最大可能 的每组人数 kkk(k≤kmaxk \\le kmaxk≤kmax)以及对应的游猎天数。若问题无解,输出 No solution 。

    输入格式

    多组数据,每组一行,包含两个正整数 nnn 和 kmaxkmaxkmax 。输入直到文件结束。

    输出格式

    对每组数据,输出一行,格式为:k persons/group, d days
    其中 kkk 为小组规模,ddd 为所需天数。若 d=1d = 1d=1 则输出 day ,否则输出 days 。若无解,输出 No solution 。

    样例输入

    4 1
    4 2
    4 3
    4 4

    样例输出

    No solution
    2 persons/group, 3 days
    2 persons/group, 3 days
    4 persons/group, 1 day


    题目分析

    问题转化

    我们可以将问题抽象为一个 组合设计问题 :

    • 有 nnn 个元素(参与者)。
    • 需要设计若干“块”(每天的分组),每个块是若干个子集(组),每个子集大小均为 kkk ,且所有子集互不相交(每天每人只在一个组)。
    • 要求任意两个元素 恰好同组一次(既满足“至少一次”又满足“至多一次”)。

    这实际上是构造一个 可分解的平衡不完全区组设计(Resolvable Balanced Incomplete Block Design\\texttt{Resolvable Balanced Incomplete Block Design}Resolvable Balanced Incomplete Block Design,简称 RBIBD\\texttt{RBIBD}RBIBD),其中参数:

    • v=nv = nv=n(元素个数)
    • kkk(块大小)
    • λ=1\\lambda = 1λ=1(每对元素出现次数)
    • 设计是可分解的(每天的分组是一个平行类,覆盖所有元素)

    数学条件推导

    设游猎进行 ddd 天,则:

  • 每天产生的不同对数
    每天有 nk\\frac{n}{k}kn​ 个组(因为 kkk 必须整除 nnn),每组有 (k2)\\binom{k}{2}(2k​) 对不同参与者。
    每天总对数为:
    nk⋅(k2)=nk⋅k(k−1)2=n(k−1)2
    \\frac{n}{k} \\cdot \\binom{k}{2} = \\frac{n}{k} \\cdot \\frac{k(k-1)}{2} = \\frac{n(k-1)}{2}
    kn​⋅(2k​)=kn​⋅2k(k−1)​=2n(k−1)​

  • 需要覆盖的总对数
    所有参与者两两配对的总数为 (n2)=n(n−1)2\\binom{n}{2} = \\frac{n(n-1)}{2}(2n​)=2n(n−1)​ 。

  • 天数公式
    由于每对恰好出现一次,所以:
    d⋅n(k−1)2=n(n−1)2
    d \\cdot \\frac{n(k-1)}{2} = \\frac{n(n-1)}{2}
    d⋅2n(k−1)​=2n(n−1)​

    解得:
    d=n−1k−1
    d = \\frac{n-1}{k-1}
    d=k−1n−1​

  • 因此,必要条件为:

    • k∣nk \\mid nk∣n(保证每天组数为整数)
    • (k−1)∣(n−1)(k-1) \\mid (n-1)(k−1)∣(n−1)(保证天数为整数)

    存在性条件

    上述两个整除条件是必要条件。对于组合设计,通常还需要满足一些其他存在性条件(例如 nnn 和 kkk 的数值关系),但本题的输入数据似乎默认:只要满足这两个整除条件,就存在合法的分组方案。因此我们只需检查这两个条件即可。

    特殊情况

  • k=nk = nk=n
    所有人一组,一天即可完成。此时公式 d=n−1k−1d = \\frac{n-1}{k-1}d=k−1n−1​ 中 k−1=n−1k-1 = n-1k−1=n−1 ,天数为 111 。注意 k=nk = nk=n 时必然满足两个整除条件。
  • k=1k = 1k=1
    每人一组,无法满足“任意两人同组”的条件,因此只有当 n=1n = 1n=1 时才可能有效(此时自己和自己“同组”)。
  • n=1n = 1n=1
    只有一个人,任意 k≥1k \\ge 1k≥1 都无意义,通常规定 k=1,d=1k = 1, d = 1k=1,d=1 。
  • 解题步骤

    对于给定的 nnn 和 kmaxkmaxkmax :

  • 若 n≤kmaxn \\le kmaxn≤kmax ,则最优解为 k=nk = nk=n(一天完成)。
  • 否则,从 k=kmaxk = kmaxk=kmax 向下枚举到 222 ,找到第一个满足:
    • n%k==0n \\% k == 0n%k==0
    • (n−1)%(k−1)==0(n-1) \\% (k-1) == 0(n−1)%(k−1)==0
      的 kkk 。
  • 若枚举后仍未找到,且 n=1n = 1n=1 且 kmax≥1kmax \\ge 1kmax≥1 ,则 k=1k = 1k=1 。
  • 若最终未找到任何 kkk ,输出 No solution 。
  • 否则计算天数 ddd:
    • 若 k=nk = nk=n 或 k=1k = 1k=1,则 d=1d = 1d=1
    • 否则 d=(n−1)/(k−1)d = (n-1) / (k-1)d=(n−1)/(k−1)
  • 按格式输出,注意 day 和 days 的单复数。

  • 算法复杂度

    由于 kmaxkmaxkmax 可能很大,最坏情况下需枚举 O(kmax)O(kmax)O(kmax) 次。但 kmaxkmaxkmax 本身也是输入值,在合理的输入范围内(例如 10910^9109 以内)直接枚举是可行的。
    每个检查为 O(1)O(1)O(1) ,总体时间复杂度 O(kmax)O(kmax)O(kmax) 每组数据。


    代码实现

    // Safari Holiday
    // UVa ID: 799
    // Verdict: Accepted
    // Submission Date: 2026-01-24
    // UVa Run Time: 0.000s
    //
    // 版权所有(C)2026,邱秋。metaphysis # yeah dot net

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

    int main() {
    long long n, kmax;
    while (cin >> n >> kmax) {
    long long bestK = –1;
    // 如果允许所有人一组
    if (n <= kmax) bestK = n;
    else {
    // 从大到小搜索第一个满足整除条件的 k
    for (long long k = kmax; k >= 2; —k)
    if (n % k == 0 && (n – 1) % (k – 1) == 0) {
    bestK = k;
    break;
    }
    }
    // 处理 n=1 的特殊情况
    if (n == 1 && kmax >= 1) bestK = 1;

    if (bestK == –1) cout << "No solution\\n";
    else {
    long long days;
    if (bestK == n || bestK == 1) days = 1;
    else days = (n – 1) / (bestK – 1);
    cout << bestK << " persons/group, " << days << " day";
    if (days > 1) cout << 's';
    cout << '\\n';
    }
    }
    return 0;
    }


    总结

    本题关键在于将实际问题转化为组合设计模型,并推导出两个简洁的整除条件:

  • k∣nk \\mid nk∣n
  • (k−1)∣(n−1)(k-1) \\mid (n-1)(k−1)∣(n−1)
  • 然后通过从大到小枚举 kkk 找到满足条件且不超过 kmaxkmaxkmax 的最大值,最后计算天数并输出即可。注意处理好边界情况 k=nk = nk=n 和 n=1n = 1n=1 。

    赞(0)
    未经允许不得转载:171主机测评 » UVa 799 Safari Holiday
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址