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

早两天做了【枚举】无序三元组a*b*c问题加强版-CSDN博客,今天老师又给孩子们安排了这个无序三元组a*b*c问题加强版之2,K的最大值达到了10^12,按之前的双循环思路又过不了,看来只能用一个循环才能搞定。题目如下:

题面翻译

给出一个正整数 𝐾,问有多少三元组 (𝑎,𝑏,𝑐)满足 𝑎×𝑏×𝑐≤𝐾?

制約

  • 1≤  𝐾≤ 10^12
  • 1≤ 𝑎,𝑏,𝑐 ≤ 𝐾
4个样例输入:2,10,31415,1000000000000
对应样例输出:4,53,1937281,402439152166882

经过仔细思考,我们可以找到用一个循环来解决的思路:

1)由于a,b,c可以任意交换位置,所以只要从1开始枚举a到小于等于a^3结束,分别计算出a*b*c≤k 且a≤b≤c的情况计数,再根组合方式直接计算出该方案的累计数。

比如K=10,我们可以这样分析:先计算最大的C值:maxC = k / a / b

(1)当a=1,b=1的情况,c可以取1-10,那么ans += (maxC - b + 1) * 3 - 2,减2就是排除c也为1时,只有一种组合,其它情况是3种组合;

(2)当a=1,b=2,c不能从1开始取,因为在第一步已经计算过了,只能取2-5,那么ans += (maxC - b + 1) * 6-3 ,减3时因为当c取2与b值相同时只有3种组合,而abc各不相同时有6种组合。

(3)当a=1的情况枚举完后,需要再枚举a++的情况。但这个a要到什么时候开始+1呢?按照上面分析思路,当maxC值小于b时就要加了,因为当maxC小于b的情况组合前面已经计算进来了。

(4)直到a*a*a>K时结算循环,但因题意K值最大为10^12,不能直接用a*a*a>K这个表达式,这样会超出long long数据范围,所以只能用k / a / a / a < 1来结束。

具体代码如下:

#include<bits/stdc++.h>
using namespace std;
int main() { //无序三元组a*b*c问题加强版 2
	long long k, ans = 0;
	cin >> k;
	long long a = 1, b = 1;
	while (1) { //只要循环到a^3<=K
		long long maxC = k / a / b;
		if (a == b) //ab相同时
			ans += (maxC - b + 1) * 3 - 2;//abc相同时只有一种组合,其余是3种组合
		else { //ab不同时
			if (maxC < b) {
				a++;
				b = a - 1;
				if (k / a / a / a < 1) break; //只要循环到a^3<=K,不能用a*a*a>k,超数据范围
			} else if (maxC >= b) {
				ans += (maxC - b + 1) * 6 - 3; //abc各不同时可组合6种,c选择与b相同时只有3种
			} 
		}
		b++;
	}
	cout << ans;
	return 0;
}

  • 10
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值