import itertools

# --------------------------
# 配置参数 - 可根据需求修改
# --------------------------
CONFIG = {
    # 基础系数列表
    'base_coefficients': [36.5, 41.5, 59, 68.5, 74, 91.5] ,
    # 目标值
    'target':82000,
    # 单个系数乘积的最大限制
    'max_product': 129000,
    # 最大变量数量（根据问题特点固定为3以提高速度）
    'max_vars': 3,
    # 目标值阈值（超过此值使用3变量）
    'target_threshold': 259000,
    # 减少波动范围以加快计算
    'fluctuation_range': [i * 0.5 for i in range(-2, 3)],  # ±1.0范围，步长0.5
    # 限制解的数量以避免不必要计算
    'max_solutions_per_combo': 20,
    # 最终筛选的最佳解数量
    'max_best_solutions': 4,
    # 平衡解的数量
    'balanced_solutions_count': 2
}

def find_solutions(config):
    """优化版：采用数学推导和剪枝策略加速求解"""
    solutions = []
    # 提取配置参数
    target = config['target']
    base_coefficients = config['base_coefficients']
    max_product = config['max_product']
    max_vars = config['max_vars']
    target_threshold = config['target_threshold']
    fluctuations = config['fluctuation_range']
    max_solutions = config['max_solutions_per_combo']
    
    # 根据目标值确定变量数量（直接使用3变量以加速）
    num_vars = 3 if target > target_threshold else min(3, max_vars)
    
    # 对系数排序，优先尝试大系数组合（减少迭代次数）
    coefficients = sorted(base_coefficients, reverse=True)
    
    # 只处理3变量情况，这是最可能找到解的组合且效率最高
    # 生成系数组合（只取较大的系数，小系数组合可能性低）
    start_idx = 0
    end_idx = min(5, len(coefficients))  # 只取前5个较大的系数组合
    for combo in itertools.combinations(coefficients[start_idx:end_idx], num_vars):
        # 计算每个系数的可能值范围（使用更严格的范围）
        ranges = []
        valid = True
        for coeff in combo:
            if coeff <= 0:
                valid = False
                break
            # 计算更精确的取值范围
            min_val = max(1, int((target - (max_product * (num_vars - 1))) / coeff))
            max_val = min(int(max_product / coeff), int(target / coeff))
            if min_val > max_val:
                valid = False
                break
            ranges.append(range(min_val, max_val + 1))
        
        if not valid:
            continue
        
        # 优化搜索顺序：先处理中间变量，减少外层循环次数
        # 对于3变量，固定前两个变量的范围，计算第三个变量
        coeff1, coeff2, coeff3 = combo
        range1, range2, range3 = ranges
        
        # 限制第一个变量的范围，只取中间部分（加速）
        step = max(1, len(range1) // 20)  # 跳步采样，减少50倍计算量
        for x in range1[::step]:
            product1 = coeff1 * x
            remaining1 = target - product1
            
            if remaining1 <= 0:
                continue
                
            # 计算第二个变量的有效范围
            min_y = max(range2.start, int((remaining1 - (coeff3 * range3.stop)) / coeff2))
            max_y = min(range2.stop - 1, int((remaining1 - (coeff3 * range3.start)) / coeff2))
            
            if min_y > max_y:
                continue
                
            # 对第二个变量也进行跳步采样
            y_step = max(1, (max_y - min_y) // 20)
            for y in range(min_y, max_y + 1, y_step):
                product2 = coeff2 * y
                remaining2 = remaining1 - product2
                
                if remaining2 <= 0:
                    continue
                    
                # 直接计算第三个变量，无需循环
                if remaining2 % coeff3 == 0:
                    z = int(remaining2 / coeff3)
                    if z in range3:
                        product3 = coeff3 * z
                        # 验证总和
                        if abs(product1 + product2 + product3 - target) < 1e-6:
                            solutions.append({
                                'coefficients': combo,
                                'values': (x, y, z),
                                'total': target,
                                'num_vars': num_vars,
                                'products': (product1, product2, product3)
                            })
                            # 找到足够解后提前退出
                            if len(solutions) >= max_solutions:
                                return solutions
    
    # 如果没有找到解，再尝试系数波动（简化版）
    if not solutions and len(fluctuations) > 0:
        for combo in itertools.combinations(coefficients[:4], num_vars):  # 只取前4个大系数
            # 生成波动组合（减少波动数量）
            fluctuated_combos = []
            for i in range(num_vars):
                if i == 0:  # 只对第一个系数进行波动
                    fluctuated_combos.append([combo[i] + d for d in fluctuations])
                else:
                    fluctuated_combos.append([combo[i]])  # 其他系数不波动
            
            for fluctuated_combo in itertools.product(*fluctuated_combos):
                if any(c <= 0 for c in fluctuated_combo):
                    continue
                
                # 计算变量范围
                ranges = []
                valid = True
                for coeff in fluctuated_combo:
                    min_val = max(1, int((target - (max_product * (num_vars - 1))) / coeff))
                    max_val = min(int(max_product / coeff), int(target / coeff))
                    if min_val > max_val:
                        valid = False
                        break
                    ranges.append(range(min_val, max_val + 1))
                
                if not valid:
                    continue
                
                # 同样的优化搜索方式
                coeff1, coeff2, coeff3 = fluctuated_combo
                range1, range2, range3 = ranges
                
                step = max(1, len(range1) // 20)
                for x in range1[::step]:
                    product1 = coeff1 * x
                    remaining1 = target - product1
                    if remaining1 <= 0:
                        continue
                        
                    min_y = max(range2.start, int((remaining1 - (coeff3 * range3.stop)) / coeff2))
                    max_y = min(range2.stop - 1, int((remaining1 - (coeff3 * range3.start)) / coeff2))
                    if min_y > max_y:
                        continue
                        
                    y_step = max(1, (max_y - min_y) // 20)
                    for y in range(min_y, max_y + 1, y_step):
                        product2 = coeff2 * y
                        remaining2 = remaining1 - product2
                        if remaining2 <= 0:
                            continue
                            
                        z = remaining2 / coeff3
                        if abs(z - round(z)) < 1e-6:
                            z = int(round(z))
                            if z in range3:
                                product3 = coeff3 * z
                                if abs(product1 + product2 + product3 - target) < 1e-6:
                                    solutions.append({
                                        'coefficients': fluctuated_combo,
                                        'values': (x, y, z),
                                        'total': target,
                                        'num_vars': num_vars,
                                        'fluctuated': True,
                                        'products': (product1, product2, product3)
                                    })
                                    if len(solutions) >= max_solutions:
                                        return solutions
    
    return solutions

def select_best_solutions(solutions, config):
    """简化版筛选函数，提高速度"""
    if not solutions:
        return []
    
    # 提取配置参数
    max_best = config['max_best_solutions']
    balanced_count = config['balanced_solutions_count']
    
    # 计算每个解的平衡分数（使用简化计算）
    for sol in solutions:
        # 使用乘积的方差作为平衡分数（值越小越平衡）
        p1, p2, p3 = sol['products']
        mean = (p1 + p2 + p3) / 3
        sol['balance_score'] = (abs(p1 - mean) + abs(p2 - mean) + abs(p3 - mean)) / 3  # 改用绝对值和，更快
    
    # 按平衡分数排序
    solutions.sort(key=lambda x: x['balance_score'])
    
    # 选择最佳解
    result = []
    # 先选平衡解
    result.extend(solutions[:balanced_count])
    # 再选普通解
    result.extend(solutions[balanced_count:balanced_count + (max_best - balanced_count)])
    
    return result[:max_best]

def main():
    # 查找所有可能的解（优化版，速度更快）
    all_solutions = find_solutions(CONFIG)
    
    if not all_solutions:
        print("未找到任何解")
        return
    
    # 选择最佳解
    best_solutions = select_best_solutions(all_solutions, CONFIG)
    
    # 处理解，将系数按从小到大排序
    processed_solutions = []
    for sol in best_solutions:
        # 组合系数和值并排序
        combined = list(zip(sol['coefficients'], sol['values'], sol['products']))
        combined_sorted = sorted(combined, key=lambda x: x[0])  # 按系数排序
        sorted_coeffs, sorted_values, sorted_products = zip(*combined_sorted)
        
        processed_sol = sol.copy()
        processed_sol['sorted_coefficients'] = sorted_coeffs
        processed_sol['sorted_values'] = sorted_values
        processed_sol['sorted_products'] = sorted_products
        processed_sol['is_balanced'] = len(processed_solutions) < CONFIG['balanced_solutions_count']
        processed_solutions.append(processed_sol)
    
    # 按排序后的系数组合分组显示结果
    combo_groups = {}
    for sol in processed_solutions:
        combo_key = sol['sorted_coefficients']
        if combo_key not in combo_groups:
            combo_groups[combo_key] = []
        combo_groups[combo_key].append(sol)
    
    # 显示每个组合及其解
    for combo, solutions in combo_groups.items():
        coeff_labels = [chr(97 + i) for i in range(len(combo))]  # a, b, c...
        combo_str = ", ".join([f"{label}={coeff:.1f}" for label, coeff in zip(coeff_labels, combo)])
        print(f"组合: {combo_str} ({len(solutions)} 个有效解)")
        
        for i, sol in enumerate(solutions, 1):
            # 第一行：未知数
            values_str = ", ".join([f"{chr(120 + j)}={val}" for j, val in enumerate(sol['sorted_values'])])
            print(f"  {i}. {values_str},")
            
            # 第二行：乘积和总和
            products_str = ", ".join([f"{label}*{chr(120 + j)}={p:.1f}" 
                                    for j, (label, p) in enumerate(zip(coeff_labels, sol['sorted_products']))])
            balanced_tag = " [平衡解]" if sol['is_balanced'] else ""
            print(f"  {products_str}, 总和 = {sol['total']:.1f}{balanced_tag}")
        
        print()

if __name__ == "__main__":
    main()
