【枚举】无序三元组a*b*c问题加强版

昨天小孩子上课老师给的作业,无序三元组普通版的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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值