T602756 糕点店
代码功能说明:
-
前缀和数组f的构建:
-
将三数之和s的所有可能情况分成三个区间处理
-
每个区间内蛋糕数量的变化规律不同
-
通过前缀和可以快速计算任意s值对应的蛋糕数量
-
-
确定三数之和:
-
通过前缀和数组快速定位第k个蛋糕的三数之和
-
使用减法逐步缩小k的范围
-
-
确定具体三元组:
-
在确定s值后,通过遍历i的可能值
-
对每个i计算j的有效范围
-
最终确定唯一的三元组(i,j,k)
-
#include<bits/stdc++.h> #define ll long long // 定义 long long 类型简写为 ll,方便使用 using namespace std; const int N = 1e6 + 10; // 题目中N的最大限制 ll f[N * 3]; // 前缀和数组,用于存储不同三数之和的蛋糕数量 ll n, k; // n是参数范围,k是要找的第k个蛋糕 int main() { // 输入n和k cin >> n >> k; // 第一部分:计算三个数之和为s的蛋糕数量,并构建前缀和数组f ll num = 1; // 初始数量 // 当s在[3, n+2]范围时,蛋糕数量呈线性增长 for(int i = 3; i <= 3 + n - 1; i++) { f[i] = f[i - 1] + num; // 累加前缀和 num++; // 每次增加1 } num -= 3; // 调整num值,为下一阶段准备 // 当s在[n+3, 2n+2]范围时,蛋糕数量先保持不变然后减少 for(int i = 3 + n; i <= 3 + 2 * n - 1; i++) { f[i] = f[i - 1] + num; // 累加前缀和 num -= 2; // 每次减少2 } num += 3; // 再次调整num值 // 当s在[2n+3, 3n]范围时,蛋糕数量又呈线性增长 for(int i = 3 + 2 * n; i <= 3 * n; i++) { f[i] = f[i - 1] + num; // 累加前缀和 num++; // 每次增加1 } // 第二部分:确定第k个蛋糕的三数之和s ll id; // 存储找到的三数之和 // 遍历所有可能的三数之和 for(int i = 1; i <= 3 * n; i++) { if(k - f[i] > 0) { k -= f[i]; // 如果k大于当前和的蛋糕数量,减去这部分 } else { id = i; // 找到对应的三数之和 break; // 退出循环 } } // 第三部分:在确定的三数之和id下,找到具体的(i,j,k)组合 for(ll i = 1; i <= min(n, id - 2); i++) { // 计算j的可能取值范围 ll minj = max(1ll, id - i - n); // j的最小值 ll maxj = min(n, id - i - 1); // j的最大值 if(minj > maxj) continue; // 无效范围则跳过 ll cnt = maxj - minj + 1; // 当前i对应的有效j的数量 if(k > cnt) { k -= cnt; // 如果k大于当前i对应的蛋糕数量,减去这部分 } else { // 找到具体的j值 ll j = minj + k - 1; // 计算k值(这里t是第三个参数) ll t = id - i - j; // 输出结果 cout << i << " " << j << " " << t << endl; return 0; // 直接结束程序 } } return 0; }

浙公网安备 33010602011771号