P12711 [KOI 2021 Round 1] 棒球赛季
解题思路
这道题目需要计算在满足特定约束条件下的最大棒球比赛场数。关键点在于理解比赛场数的计算方式和约束条件。
核心思路
-
比赛场数计算:
-
同一地区内比赛:每个地区有M支队伍,每两队之间进行A场比赛
-
跨地区比赛:不同地区的每两队之间进行B场比赛
-
约束条件:A = k × B(k为整数且≥1)
-
-
数学建模:
-
同一地区内比赛总数:N × [M×(M-1)/2] × A
-
跨地区比赛总数:[N×(N-1)/2] × M² × B
-
总比赛数 = (N×M×(M-1)/2 × k + N×(N-1)/2 × M²) × B
-
-
二分查找:
-
在满足总比赛数 ≤ D 的条件下,寻找最大的B值
-
通过二分查找确定最大的整数B,使得总比赛数不超过D
-
代码注释
#include<bits/stdc++.h> #define ll long long // 定义long long类型别名 using namespace std; const int N = 2e5 + 10, inf = 0x3f3f3f3f; void solve() { ll n, m, k, d; cin >> n >> m >> k >> d; // 输入地区数、每地区队伍数、系数k、最大比赛数D // 计算系数t1:同一地区内比赛的系数部分 ll t1 = n * m * (m - 1) / 2 * k; // 计算系数t2:跨地区比赛的系数部分 ll t2 = n * (n - 1) / 2 * m * m; ll ans = -1; // 初始化答案为-1(表示无解) ll l = 1, r = 1e9; // 二分查找的左右边界,B的取值范围[1, 10^9] // 二分查找寻找最大的B值 while(l <= r) { ll mid = l + r >> 1; // 取中间值 // 检查当前B=mid时总比赛数是否不超过D if((t1 + t2) * mid <= d){ l = mid + 1; // 满足条件,尝试更大的B值 ans = mid; // 更新当前找到的最大有效B值 } else r = mid - 1; // 不满足条件,尝试更小的B值 } if(ans == -1) cout << -1 << endl; // 没有找到合适的B值 else cout << (t1 + t2) * ans << endl; // 输出最大总比赛数 } int main() { int t; cin >> t; // 输入测试用例数量 while(t--) { solve(); // 处理每个测试用例 } return 0; } // 注释说明: // bd = n * m * (m - 1) / 2 * a; // 同一地区内比赛总数 // wd = n * (n - 1) / 2 * m * m * b; // 跨地区比赛总数 // a = k * b; // 约束条件 // wd + bd <= d // 总比赛数约束 // 代入约束条件后: // bd = n * m * (m - 1) / 2 * k * b; // wd = n * (n - 1) / 2 * m * m * b; // bd + wd = n * m * (m - 1) / 2 * k * b + n * (n - 1) / 2 * m * m * b <= d // 提取公因式: // t1 = n * m * (m - 1) / 2 * k // 同一地区比赛系数 // t2 = n * (n - 1) / 2 * m * m // 跨地区比赛系数 // bd + wd = (t1 + t2) * b <= d // 总比赛数表达式
公式代码
#include<bits/stdc++.h> #define ll long long // 定义long long类型别名,防止整数溢出 using namespace std; const int N = 2e5 + 10, inf = 0x3f3f3f3f; void solve() { ll n, m, k, d; cin >> n >> m >> k >> d; // 输入:地区数、每队队伍数、系数k、最大比赛数 // 计算系数t1:同一地区内比赛的系数 // n个地区 × 每个地区m支队伍 × 每队与其他(m-1)队比赛 × 系数k ll t1 = n * m * (m - 1) / 2 * k; // 计算系数t2:跨地区比赛的系数 // n个地区中选2个的组合数 × 每个地区m支队伍 × 另一地区m支队伍 ll t2 = n * (n - 1) / 2 * m * m; // 计算最大可能的B值:D除以总系数 ll ans = d / (t1 + t2); // 计算对应的总比赛数 ans = (t1 + t2) * ans; // 输出结果:如果结果为0说明无解,否则输出最大比赛数 if(ans == 0) cout << -1 << endl; else cout << ans << endl; } int main() { int t; cin >> t; // 输入测试用例数量 while(t--) { solve(); // 处理每个测试用例 } return 0; } // 公式推导注释: // bd = n * m * (m - 1) / 2 * a; // 同一地区内比赛总数 // wd = n * (n - 1) / 2 * m * m * b; // 跨地区比赛总数 // a = k * b; // 题目约束条件 // wd + bd <= d // 总比赛数限制 // 代入约束条件: // bd = n * m * (m - 1) / 2 * k * b; // 将a=k*b代入 // wd = n * (n - 1) / 2 * m * m * b; // 保持不变 // bd + wd = (n*m*(m-1)/2*k + n*(n-1)/2*m²) * b <= d // 提取公因式: // t1 = n * m * (m - 1) / 2 * k // 同一地区比赛系数 // t2 = n * (n - 1) / 2 * m * m // 跨地区比赛系数 // 总比赛数 = (t1 + t2) * b ≤ d // 简化后的表达式

浙公网安备 33010602011771号