import random
import math
import statistics
def generate_split():
# ======================== 配置参数 ========================
target_sum = 156291 # 必须精确匹配的目标总和
multiplier = 590 # 乘数
max_product = 10000 # 最大值(不可改变)
min_product = 5000 # 放宽最小值(从6000→5000)
max_duplicates = 3 # 放宽重复限制(从2→3)
max_consecutive_ratio = 0.8 # 放宽连续值比例
# ============================================================
# 1. 计算灵活的拆分数n(确保有解)
# 必须满足:n ≥ target_sum/max_product(因为最大值固定)
min_possible_n
= math.
ceil(target_sum
/ max_product
) # 156291/10000≈16 → 最小n=16 # 放宽上限计算,确保有足够调整空间
max_possible_n = min_possible_n + 5 # 在最小n基础上+5,增加灵活性
n = min_possible_n # 从最小n开始,确保不超过最大值限制
# 2. 拆分值范围(严格保证最大值对应的拆分值)
max_x = round(max_product / multiplier, 1) # 10000/590≈16.95→16.9
min_x = round(min_product / multiplier, 1) # 5000/590≈8.47→8.5
# 最大值对应的拆分值严格限制
strict_max_x = max_x
# 3. 辅助函数
def is_consecutive(a, b):
return 0.1 <= abs(a
- b
) <= 0.2
def get_product(x):
return round(x * multiplier)
def is_valid_product(x):
p = get_product(x)
return p <= max_product # 只严格限制最大值,最小值可适当放宽
def consecutive_ratio(values):
if len(values) < 2:
return 0.0
consecutive_count = sum(1 for i in range(len(values)-1) if is_consecutive(values[i], values[i+1]))
return consecutive_count / (len(values) - 1)
# 4. 生成初始拆分值(优先使用接近平均值的范围)
avg_product = target_sum / n # 目标平均乘积
values = []
count = {}
attempts = 0
max_attempts = 100000
while len(values) < n and attempts < max_attempts:
attempts += 1
# 围绕平均值生成,增加调整余量
x = round(random.uniform(
max(min_x - 0.5, avg_product/multiplier - 2),
min(strict_max_x, avg_product/multiplier + 2)
), 1)
if not is_valid_product(x): # 只检查是否超过最大值
continue
if count.get(x, 0) >= max_duplicates:
continue
values.append(x)
count[x] = count.get(x, 0) + 1
if len(values) < n:
# 极端情况:强制补全,忽略部分限制
while len(values) < n:
x = round(random.uniform(min_x - 1, strict_max_x), 1)
if is_valid_product(x):
values.append(x)
count[x] = count.get(x, 0) + 1
# 5. 调整连续值(适度放宽)
def adjust_consecutive(values):
current_ratio = consecutive_ratio(values)
if current_ratio <= max_consecutive_ratio:
return values
adjusted = values.copy()
modify_count = int((current_ratio - max_consecutive_ratio) * len(adjusted)) + 1
for _ in range(modify_count):
pos = random.randint(1, len(adjusted)-1)
prev = adjusted[pos-1]
for __ in range(100):
new_x = round(random.uniform(min_x - 0.5, strict_max_x), 1)
if (not is_consecutive(new_x, prev) and
is_valid_product(new_x)): # 放宽重复检查
old_x = adjusted[pos]
count[old_x] -= 1
if count[old_x] == 0:
del count[old_x]
count[new_x] = count.get(new_x, 0) + 1
adjusted[pos] = new_x
break
return adjusted
values = adjust_consecutive(values)
# 6. 总和调整(核心:不惜一切代价保证总和,仅严格限制最大值)
products = [get_product(x) for x in values]
diff = target_sum - sum(products)
# 阶段1:常规调整
indices = list(range(n))
random.shuffle(indices)
for i in indices:
if diff == 0:
break
current_x = values[i]
step = 0.1 if diff > 0 else -0.1
new_x = round(current_x + step, 1)
if new_x <= strict_max_x and count.get(new_x, 0) < max_duplicates + 1:
# 允许最小值超限,只限制最大值
count[current_x] -= 1
if count[current_x] == 0:
del count[current_x]
values[i] = new_x
products[i] = get_product(new_x)
count[new_x] = count.get(new_x, 0) + 1
diff = target_sum - sum(products)
# 阶段2:强化调整(进一步放宽限制)
if diff != 0:
indices = list(range(n))
random.shuffle(indices)
for i in indices:
if diff == 0:
break
current_p = products[i]
# 只限制最大值方向的调整
max_add = max_product - current_p if diff > 0 else float('inf')
max_sub = float('inf') # 最小值方向不限制
adjust
= min
(abs(diff
), max_add
) if diff
> 0 else -min
(abs(diff
), max_sub
)
if adjust == 0:
continue
new_p = current_p + adjust
new_x = round(new_p / multiplier, 1)
if new_x <= strict_max_x: # 仅确保不超过最大值
# 完全放宽重复限制
count[values[i]] -= 1
if count[values[i]] == 0:
del count[values[i]]
values[i] = new_x
products[i] = new_p
count[new_x] = count.get(new_x, 0) + 1
diff = target_sum - sum(products)
# 阶段3:终极保证(最后一个值无任何限制,除了最大值)
if diff != 0:
last_idx = n - 1
current_p = products[last_idx]
required_p = current_p + diff
# 确保不超过最大值
if required_p > max_product:
required_p = max_product
# 此时需要从其他值削减,重新分配
reduce_from = random.sample(range(last_idx), min(5, last_idx))
total_reduce = required_p - current_p - diff
for i in reduce_from:
if total_reduce >= diff:
break
reduce_amt = min(500, total_reduce, products[i] - 1000) # 至少保留1000
products[i] -= reduce_amt
values[i] = round(products[i] / multiplier, 1)
total_reduce += reduce_amt
required_p = current_p + (diff + total_reduce)
new_x = round(required_p / multiplier, 1)
# 确保最后一个值不超过最大拆分值
if new_x > strict_max_x:
new_x = strict_max_x
required_p = get_product(new_x)
# 更新最后一个值
old_x = values[last_idx]
count[old_x] -= 1
if count[old_x] == 0:
del count[old_x]
values[last_idx] = new_x
products[last_idx] = required_p
count[new_x] = count.get(new_x, 0) + 1
diff = target_sum - sum(products)
# 7. 最终验证(总和必须正确,最大值必须遵守)
final_sum = sum(products)
over_max = [p for p in products if p > max_product]
if over_max:
return f"❌ 严重错误:{len(over_max)}个乘积超过最大值10000"
if final_sum != target_sum:
return f"❌ 致命错误:无法调整至目标总和({final_sum}≠{target_sum})"
# 8. 结果统计
under_min = [p for p in products if p < min_product]
under_min_desc = f"({len(under_min)}个低于放宽后的最小值{min_product})" if under_min else ""
duplicates = [x for x in count if count[x] > 1]
duplicate_desc = f"共{len(duplicates)}个值重复: {[f'{x}({count[x]}次)' for x in duplicates[:5]]}{'...' if len(duplicates)>5 else ''}"
final_ratio = consecutive_ratio(values)
consecutive_desc = f"{sum(1 for i in range(n-1) if is_consecutive(values[i], values[i+1]))}组(比例{final_ratio:.0%})"
std_dev = round(statistics.stdev(values), 2) if n >= 2 else 0
# 输出结果
return "\n".join([
"=== 拆分结果(放宽限制版) ===",
f"状态: ✅ 有效(总和匹配,最大值严格遵守){under_min_desc}",
f"拆分数: {n}个(最小必要数量)",
f"连续值对: {consecutive_desc}",
f"重复情况: {duplicate_desc}",
f"分散度(标准差): {std_dev}",
f"总和验证: {final_sum} == {target_sum}",
"乘积明细(前5项): " + " + ".join([f"{x}×{multiplier}={p}" for x, p in zip(values[:5], products[:5])]) + (" + ..." if n>5 else ""),
f"拆分值(前5项): {values[:5]} {'...' if n>5 else ''}"
])
if __name__ == "__main__":
print(generate_split())