昨天小孩子上课老师给的作业,无序三元组普通版的K只有10^6,三个循环可以轻松通过,现这个加强版的K最大值为10^8,不管如何优化和剪枝,三循环的版本最后一个测试就是通不过,显示超时。原题如下:
经过分析本题三元组的特点,我们可以将3循环转为2循环,具体优化思路如下:
1)外循环只要循环到K/2。因为大于K/2的后半部分数值三数相乘要小于K,只能是1,对于数字较大的K这样可以减少很多次循环。
2)将K除以第一个数a,可计算出最的b*c的最大值,内循环枚举b,再将b*c÷b可计算出最大的C,所以内循环我们只要枚举到最大的C为止,不必到≤K去,减少循环次数。
3)a和b的最大值已确定后,原三循环方案中的第3个循环枚举c就不必了,可以直接累加计数,大大减少循环次数。
4)内循环中的b为1时可以不必循环,按题意可以直接累加计数。
5)最后再累加K后半部分的数值情况,注意K为奇数时要加1。
附:详细代码及备注说明。
#include<bits/stdc++.h>
using namespace std;
int main() {
int k;
long long ans = 0;
cin >> k;
for (int a = 1; a <= k / 2; a++) { //只要循环一半的次数,后半数BC只能是1,直接可累加
int maxBC = k / a;
for (int b = 1; b <= maxBC / b; b++) {
int maxC = maxBC / b;
if (b == 1) { //第二个数为1时直接计算
ans += maxC * 2 - 1; //因为是题目要求无序,除1外第二、三位数可交换,计算2次
continue;
}
ans += (maxC - b + 1) * 2 - 1; //按规则直接计算个数
}
}
k % 2 == 1 ? ans += k / 2 + 1 : ans += k / 2; //计算后半部分情况,奇数要多加1次
cout << ans;
return 0;
}