水题:面向测试用例编程

问题描述

原问题

个人认为原问题的范围应该是不可靠的,只要过了给定的用例就可以

题目简述
要求输出n个正整数,他们的和为s, 每个元素值的范围在[1,m]之内。求输出所有可能的组合结果。

输入: n = 2, m = 6, s = 10,下面简述为(n, m, s), 即(2,6,10)

输出:
(4,6)
(5,5)

注意:
(6,4)属于重复的结果

边界约束:
1 <= n <= 100
1 <= m <= 1e9
1 <= s <= 1e5

测试用例:
(2, 6, 10)
(6, 6, 8)
(3, 1e5, 20)
(10, 10, 100)
(100, 100, 10000)

可行思路

vector<vector<int>> res;

void helper(int pos, int left, const int m, vector<int>&tmp) {

	if (pos == tmp.size()) {
		if (left == 0) {
			auto cpy = tmp;
			//std::sort(cpy.begin(), cpy.end());
			res.emplace_back(std::move(cpy));
		}
		return;
	}

	
	// 剪枝1: 后面的值必定不小于前面的值(保证不重)
	int meta_x = pos > 0 ? tmp[pos - 1] : 1;

	// 剪枝2: 最后一个槽不再穷举
	if (pos == tmp.size() - 1) {
		// 触发写入
		
		if (left <= m) {
			tmp[pos] = left;
			helper(pos + 1, 0, m, tmp);
		}
		return;
	}
	
	
	int l = meta_x;

	int r = m;

	int left_cnt = tmp.size() - 1 - pos; // 剩余槽位

	// 剪枝3: 余数全取最小值不满足题意筛掉
	if (meta_x * (left_cnt + 1) > left) return;

	// 剪枝4: 二分查找过滤无效边界
	while (l <= r) {
		int x = (r - l) / 2 + l;
		
		//  以x作余数均值其和大于left
		if (left - x < 0 || x * left_cnt > left - x) {
			r = x - 1;
		}// 余数均值大于m
		else if ((left - x) > m * left_cnt) {
			l = x + 1;
		}
		else {
			while ((left - l) > m * left_cnt) {
				l++;
			}
			tmp[pos] = l;
			helper(pos + 1, left - l, m, tmp);
			l++;
		}
	}
}

void Hello(int n, int m, int s) {
	vector<int> tmp(n, 0);

	int left = s;
	int pos  = 0;
	
	printf("===%d,%d,%d===\n", n, m, s);
	helper(0, s, m, tmp);

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值