告别交叉变异:一文读懂基于群体的增量学习算法 (PBIL)——python实现

告别交叉变异:PBIL算法原理与Python实现详解 优化算法是解决工程与科研中复杂决策问题的核心工具,其中遗传算法因模拟自然选择而广受欢迎,但交叉、变异等算子参数敏感、实现复杂,常让实践者头疼。基于群体的增量学习(PBIL)作为一种简洁高效的概率优化算法,用概率向量隐式表示种群,通过正负反馈更新分布,彻底告别传统交叉变异操作。它参数少、收敛快,特别适合二进制编码、组合优化等场景,如背包问题和函数优化。深度解析PBIL核心机制,并给出可直接运行的Python实现与调参经验,帮助算法学习者和工程师快速落地应用。 阅读详情

一、前言:一种不同的“进化”思路

在优化算法的大家庭里,遗传算法(Genetic Algorithm, GA)无疑是明星成员。它通过模拟生物界的“优胜劣汰、交叉变异”来寻找最优解。但你是否想过,我们一定要维护一个庞大的“种群”吗?

今天介绍的 基于群体的增量学习算法(Population-Based Incremental Learning, PBIL) 就给出了一个全新的答案。它属于 分布估计算法(Estimation of Distribution Algorithms, EDA) 的一种,其核心思想是:不再进化具体的“个体”,而是进化生成优秀个体的“概率模型”。

二、PBIL的核心思想:从操作个体到学习蓝图

为了更好地理解,我们来做一个对比:

  • 遗传算法 (GA):维护一个由多个解(个体)组成的种群。通过选择、交叉、变异等算子,直接对这些个体进行操作,希望好的基因能够代代相传。
  • PBIL算法:它不维护种群,而是维护一个 概率向量(Probability Vector, PV)。这个向量可以看作是生成优秀解的“蓝图”或“模板”。

假设我们要解决一个解为 n 位二进制串的问题。PBIL的概率向量 PV 就是一个 n 维的浮点数数组,其中 PV[i] 代表了在最终解的第 i 个位置上,值为 1 的概率。

算法的目标就是:通过不断从这个概率模型生成样本,并从样本中学习,持续优化这个概率向量,使其最终能够以极高的概率直接生成问题的最优解。

三、算法步骤与核心公式

PBIL的流程非常简洁优雅,主要分为以下几步:

1. 初始化 (Initialization)

创建一个概率向量 PV。在没有任何先验知识的情况下,我们通常将其所有元素初始化为 0.5。
PV = [0.5, 0.5, 0.5, ...]
这表示在每个位置上,生成 0 和 1 的概率是均等的。

2. 生成样本 (Sampling)

根据当前的概率向量 PV,随机生成 N 个候选解(个体)。例如,要生成一个个体的第 i 位,如果 PV[i] 是 0.8,那么该位有80%的概率是 1,20%的概率是 0。

3. 评估 (Evaluation)

计算这 N 个新生成的候选解的适应度值(即它们有多好)。

4. 学习与更新 (Learning & Updating)

这是PBIL的灵魂所在。
首先,从 N 个解中,找到 适应度最高 的那个解,我们称之为 best_individual。
然后,使用这个最好的解来 更新概率向量 PV,使其“朝着”这个最好解的方向移动一点。

更新公式如下:
PVnew[i]=(1−LR)⋅PVold[i]+LR⋅best_individual[i] PV_{new}[i] = (1 - LR) \cdot PV_{old}[i] + LR \cdot \text{best\_individual}[i] PVnew​[i]=(1−LR)⋅PVold​[i]+LR⋅best_individual[i]
其中:

  • LR 是 学习率 (Learning Rate),一个介于0和1之间的小数(如0.1),控制着每次更新的幅度。
  • best_individual[i] 是最优解的第 i 位(值为0或1)。

这个公式的本质是一个加权平均,它把概率向量向当前找到的最优解的方向“拉”了一把。

5. 变异 (Mutation) (可选)

为了防止概率向量过早收敛(即某些值过分接近0或1,导致多样性丧失),可以引入一个小的变异步骤,对概率向量进行轻微的随机扰动。

if (random() < mutation_prob): PV[i]=(1−mutation_shift)⋅PV[i]+mutation_shift⋅random_bit \text{if (random() < mutation\_prob): } PV[i] = (1 - \text{mutation\_shift}) \cdot PV[i] + \text{mutation\_shift} \cdot \text{random\_bit} if (random() < mutation_prob): PV[i]=(1−mutation_shift)⋅PV[i]+mutation_shift⋅random_bit

这相当于给概率向量一个机会,去探索那些当前看起来不是最优的方向。

6. 终止

重复步骤2到5,直到满足终止条件(如达到最大迭代次数,或概率向量已收敛)。

四、经典应用:One-Max问题

One-Max问题是最简单的测试函数之一,其目标是找到一个二进制串,使其包含的 1 的数量最多。对于长度为 n 的串,最优解就是全 1 串,适应度为 n。

使用PBIL解决此问题时:

  1. 初始 PV 全为 0.5。
  2. 生成的样本中,1 越多的个体适应度越高。
  3. 在更新步骤中,best_individual 中 1 的位置会使得 PV 对应位置的概率值增加。
  4. 经过多次迭代,PV 的所有元素都会趋近于 1.0,从而稳定地生成最优解。

完整python代码

import numpy as np
import matplotlib.pyplot as plt

# 设置matplotlib支持中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置中文字体为黑体
plt.rcParams['axes.unicode_minus'] = False    # 设置正常显示负号,以防坐标轴负数出错

# --- 1. 参数定义 ---
ONE_MAX_LENGTH = 50       # 问题规模:二进制串的长度
POPULATION_SIZE = 100     # 种群大小:每代生成的个体数量
LEARNING_RATE = 0.05      # 学习率:控制概率向量更新的步长
MUTATION_PROB = 0.02      # 变异概率:对概率向量进行扰动的概率
MUTATION_SHIFT = 0.05     # 变异幅度:扰动的大小
MAX_GENERATIONS = 100     # 最大迭代次数

# --- 2. 适应度函数 (One-Max问题) ---
def evaluate_fitness(individual):
    """计算个体的适应度,即二进制串中'1'的数量。"""
    return np.sum(individual)

# --- 3. PBIL算法实现 ---

# 初始化概率向量 (PV)
# 开始时,每个位置为1的概率都是0.5
prob_vector = np.full(ONE_MAX_LENGTH, 0.5)

# 用于记录每代的最优适应度,以便可视化
best_fitness_history = []
avg_fitness_history = []

print("--- PBIL算法开始运行 ---")

# 开始迭代
for generation in range(MAX_GENERATIONS):
    # --- 步骤1: 根据概率向量生成种群 ---
    # population是一个 (POPULATION_SIZE, ONE_MAX_LENGTH) 的矩阵
    # np.random.rand(...) < prob_vector 利用了NumPy的广播机制
    # 生成一个随机数矩阵,然后与概率向量逐行比较,得到布尔矩阵,再转为整数0或1
    population = (np.random.rand(POPULATION_SIZE, ONE_MAX_LENGTH) < prob_vector).astype(int)

    # --- 步骤2: 评估种群中每个个体的适应度 ---
    fitness_scores = np.array([evaluate_fitness(ind) for ind in population])

    # --- 步骤3: 找到当前种群中的最优个体 ---
    best_individual_index = np.argmax(fitness_scores)
    best_individual = population[best_individual_index]
    best_fitness = fitness_scores[best_individual_index]
    
    # 计算平均适应度
    avg_fitness = np.mean(fitness_scores)
    
    # 记录历史数据
    best_fitness_history.append(best_fitness)
    avg_fitness_history.append(avg_fitness)

    # --- 步骤4: 更新概率向量 ---
    # 公式: PV_new = (1 - LR) * PV_old + LR * best_individual
    prob_vector = (1 - LEARNING_RATE) * prob_vector + LEARNING_RATE * best_individual

    # --- 步骤5: 对概率向量进行变异 ---
    for i in range(ONE_MAX_LENGTH):
        if np.random.rand() < MUTATION_PROB:
            # 公式: PV_mutated = (1 - MS) * PV + MS * random_bit
            random_bit = np.random.randint(0, 2) # 随机选择0或1
            prob_vector[i] = (1 - MUTATION_SHIFT) * prob_vector[i] + MUTATION_SHIFT * random_bit

    # 打印当前代的信息
    if (generation + 1) % 10 == 0:
        print(f"第 {generation + 1:3d} 代: 最优适应度 = {best_fitness:2.0f}/{ONE_MAX_LENGTH}, 平均适应度 = {avg_fitness:5.2f}")

# --- 4. 结果展示 ---
print("\n--- 算法运行结束 ---")
print(f"最终概率向量 (部分): {np.round(prob_vector[:10], 2)}...")
# 根据最终的概率向量生成最终的推荐解
final_solution = (prob_vector > 0.5).astype(int)
final_fitness = evaluate_fitness(final_solution)
print(f"最终解的适应度: {final_fitness}/{ONE_MAX_LENGTH}")
print(f"最终解 (部分): {final_solution[:20]}...")


# --- 5. 可视化 ---
plt.figure(figsize=(10, 6))
plt.plot(best_fitness_history, label='每代最优适应度')
plt.plot(avg_fitness_history, label='每代平均适应度', linestyle='--')
plt.axhline(y=ONE_MAX_LENGTH, color='r', linestyle='-', label=f'理论最优值 ({ONE_MAX_LENGTH})')
plt.title('PBIL算法求解One-Max问题收敛曲线')
plt.xlabel('迭代次数')
plt.ylabel('适应度')
plt.legend()
plt.grid(True)
plt.show()

在这里插入图片描述

五、优缺点分析

优点

  • 概念简单:相比GA复杂的算子,PBIL的更新规则非常直观。
  • 计算高效:省去了维护和操作庞大种群的开销。
  • 全局信息利用:概率向量是对历史所有优秀解的统计抽象,隐式地利用了全局信息。

缺点

  • 变量无关性假设:基本PBIL假设变量(基因位)间相互独立,难以捕捉变量间的复杂关联(例如,x[1] 和 x[5] 必须同时为 1)。
  • 主要用于离散空间:基本形式主要针对二进制编码问题,解决连续问题需要对概率模型进行扩展(如使用高斯分布)。

六、总结

PBIL算法为我们提供了一种“上帝视角”的优化思路:它不关心种群中个体的“爱恨情仇”(交叉),而是通过统计和学习,直接去描绘最优解的“样貌”(概率分布)。这种从操作实例到学习模型的思想转变,正是分布估计算法的魅力所在,也为解决复杂优化问题开辟了新的道路。

从零开始学习使用 AI 欢迎踏入ClaudeCode未来世界,开启与AI协作的全新旅程。无论你是零基础新手、开发者,还是非程序员,都能通过实战项目快速掌握智能体协作技能——不再只是提问,而是指挥AI完成复杂任务。你将化身主角,在16个级别、200+实践中成长为高效创造者。真正的优势不再是会用工具,而是懂得如何让智能体为你工作。取代你的不是AI,而是会用AI的人。现在,故事从你开始👇 阅读详情

相关推荐

第28篇 sw放样特征矩形-圆-矩形学习笔记

本例演示三轮廓放样:先画中心对齐的100×100矩形草图,再在偏移100的基准面上绘制圆,最后在另一基准面画矩形。通过依次选择三个轮廓并正确设置连接点,实现矩形→圆→矩形的平滑过渡,注意连接点位置避免扭曲。

Txwtech 23

PBIL算法实战:从遗传算法参数噩梦到概率向量优雅求解

进化算法家族中,遗传算法(GA)凭借交叉与变异算子广为人知,但交叉率、变异率与种群规模的参数组合常让人陷入调参泥潭,尤其面对排班、路径等强约束问题时,优质解结构容易被交叉拆散,变异过大又会退化为随机搜索。作为估计分布算法(EDA)的早期代表,基于群体的增量学习算法(PBIL)彻底移除了交叉与变异操作,转而维护一个概率向量,通过伯努利采样生成种群、精英均值更新分布,用概率空间的变异扰动恢复多样性。这种从“维护个体”到“维护分布”的范式转变,让参数锐减、实现简洁,且天然抗噪声。PBIL在OneMax与背包问题等

weixin_32288959的博客 729

Win10平台下QT6.9.0 OpenCV 4.10.0从入门到精通

我最近开发一个视觉项目,我们从0开始记录在windows 10下 用QT6.9+OpenCV 4.10.0搞定整个项目的开发过程。以抛砖引玉,大家共同进步。

fds111111的博客 1711

分布估计算法(EDA)在优化问题中的应用与实现

本文深入探讨了分布估计算法(EDA)的核心原理及其在复杂优化问题中的应用。通过对比传统遗传算法,阐述了EDA如何通过构建和更新概率模型来高效引导搜索方向,并详细介绍了UMDA、PBIL及基于高斯模型的EDA等关键变种。文章结合函数优化、机器学习超参数调优等实战案例,展示了EDA在处理变量间存在依赖关系的高维、黑箱优化问题时的显著优势。

g8f9d0s1a2的博客 196

深入解析Zynq Ultrascale+ RF Data Converter中的PLL配置与时钟管理

本文深入解析了Zynq Ultrascale+ RF Data Converter中PLL配置与时钟管理的核心原理与实践。文章将RFDC时钟系统比作交响乐团,详细阐述了PLL作为指挥的关键作用,以及系统时钟、Tile时钟、参考时钟与采样时钟的层级关系。重点剖析了PLL配置参数(如VCO频率、分频器设置)的计算方法与稳定性考量,并提供了从IP配置使能顺序到多Tile同步、DRP访问等常见问题的实战避坑指南与调试技巧,帮助工程师构建稳定的射频信号处理基石。

7up55的博客 449

从零构建XVC协议栈:FPGA+W5300的跨界调试架构实战

本文详细介绍了如何从零构建XVC协议栈,通过FPGA与W5300以太网控制器的创新组合实现跨界调试架构。重点解析了JTAG时序逆向、TCP/IP协议栈集成与XVC协议实现,提供了硬件设计优化和性能加速技术,为嵌入式开发者和FPGA工程师提供实用的远程调试解决方案。

raspberrypi5的博客 247

2026.11.7 AI学习总结

110 你 14b 模型权重本身就要约 8.8GB,默认上下文(Ollama 在 16GB 卡上可能给到 4K)加上 KV Cache 就爆了。比如设成 2048,你输入了 500 个 token 的问题,那模型最多还能生成 1500 个 token 的回答。超出部分会被截断,模型就"看不见"了。4 如果 14b 跑起来后发现它"忘事",再逐步往上加,比如先试 4096。,根据注意力头的重要性动态分配缓存资源,重要的留显存,不重要的下沉。,单位是 token,表示模型这一次推理最多能同时"看到"多少内容。

qq_41181702的博客 359

【Bluetooth|蓝牙开发】二、蓝牙开发入门

蓝牙,是一种利用低功率无线电,支持设备短距离通信的无线电技术,能在包括移动电话、PDA、无线耳机、笔记本电脑、相关外设等众多设备之间进行无线信息交换,蓝牙工作在全球通用的2.4GHz ISM(即工业、科学、医学)频段,使用IEEE802.11协议。

Donge's Blog 1万+

MySQL建库建表操作学习笔记

SQL(Structured Query Language,结构化查询语言)是用于在关系型数据库上执行数据操作、数据检索以及数据维护的标准语言。:用于定义对数据库对象(库、表、列、索引)的操作,如 CREATE、DROP、ALTER、RENAME、TRUNCATE 等。保存可变长度的字符串(可包含字母、数字以及特殊字 符)。:用于定义对数据库记录的操作,如 INSERT、DELETE、UPDATE、SELECT 等。:用于定义对数据库、表、字段、用户的访问权限和安全级别,如 GRANT、REVOKE 等。

Eternitycai的博客 217

《UDS协议从入门到精通》系列——图解0x83:访问时间参数

详细介绍UDS协议0x83服务,目标ECU的时序参数设置有哪些注意点?

车载系统攻城狮 2138

18、项目运行与调试全攻略

本文详细介绍了在IntelliJ IDEA中进行项目运行与调试的完整流程,涵盖运行配置的创建与管理、临时配置的使用与保存、运行窗口的控制台操作及多程序并行运行的处理。同时,讲解了如何通过调试器定位和修复语法错误、运行时错误及逻辑错误,并结合ACME项目演示了第三方库Log4J的集成方法和命令行客户端的功能改进。文章还提供了调试流程图,帮助开发者系统掌握IDEA的强大调试功能,提升开发效率与代码质量。

svm4gardener的博客 75

【FreeRTOS源码学习笔记】任务创建

【FreeRTOS源码学习笔记】任务创建

2502_90565057的博客 456

基于卷积神经网络CNN实现电力负荷多变量时序预测(PyTorch版)

随着智能电网的发展,精准的电力负荷预测对能源调度和电网稳定具有重要意义。本文基于PyTorch框架,提出一种基于卷积神经网络(CNN)的多变量时间序列预测模型,用于电力负荷的短期预测。

时序笔记 988

Flink 学习日志 03:自定义一个SourceFunction,完成对Redis中数据的读取

本文介绍了在Flink中自定义SourceFunction读取Redis数据的完整流程:通过Jedis客户端连接WSL2中的Redis服务,编写RedisSource实现循环读取所有Key-value并逐条输出,结合Thread.sleep()实现每秒一条的流式效果。关键步骤包括环境准备、添加Jedis依赖、配置IDEA运行时加载provided依赖,并注意生产环境中应避免使用阻塞的keys *,改用scan命令。最终实现动态读取、实时打印,验证了Flink与Redis的数据集成能力。

木木的学习笔记 400

毕业设计:丹麦电力电价预测预测未来24小时的电价pytorch+lstm+历史特征和价格+时间序列 电价预测模型资源 完整代码数据可直接运行

毕业设计:丹麦电力电价预测预测未来24小时的电价pytorch+lstm+历史特征和价格+时间序列 电价预测模型资源 完整代码数据可直接运行

355

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

邓明 Agent 系统面试-意图识别学习笔记

不要只是做意图识别而不做测评,就好像要评估 RAG 准确性,在接口服务要测试响应时延,超时控制等等,这里也要关注意图识别准确率,如果面试官认为项目指标太高是在吹牛,关键就是回答因为 Agent 解决的是特定领域的意图识别,识别场景单一,另外就是因为用户输入相对简单。意图识别影响 prompt/spec 的加载,意图识别影响上下文组织,意图识别影响工具选择,意图识别影响 prompt 建议,意图识别得到的意图不是让模型随机生成而是候选类别里去做选择。2.意图识别的原因,以及意图识别得到的是什么?

m0_57222081的博客 209

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

CMake学习

CMake如何编译成库?1. 为什么要有库?库就是预先写好,编译好的代码集合。存在的意义,1)避免重复造轮子和重复编译,库是,你的代码在编译时直接链接它,不需要把库的源码重新编译一遍,大大节省了编译时间。;2):编译成库让别人可以直接调用我的函数,但看不到cpp源码,看不到里面的逻辑。3):大项目可以拆分给不同的团队开发不同的库,最后拼在一起。静态库:就是在程序编译和链接阶段,把库里被用到的代码部分,像打包裹一样,直接复制粘贴到最终的可执行文件(如.exe或 Linux 下的无后缀文件)里面。

m0_56487684的博客 178

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

商业经济学学习资料

商业经济学学习资料

weixin_29403917的博客 278

将物理先验嵌入机器人学习:从经典力学到 VLA 与 WAM

本文综述了将物理先验嵌入机器人学习的三条路径:数据与表示、模型架构、训练损失,强调其位置决定约束效力。通过夹取软物体案例,阐明运动学、动力学、接触与材料特性在任务中的分层作用。指出物理先验非万能,需匹配实际条件;强约束可加速学习,但误用会引入偏差。提出“有效刚度”等概念,强调主动探测与参数辨识的重要性,并警示仅靠单一方法无法保障安全执行,需结合在线验证与控制闭环。

lovely_yoshino的博客 664

【学习笔记】51单片机 模块化编程

模块化编程:把各个模块的代码放在不同的c文件里,在.h文件里提供外部可调用函数的声明,在其他.c文件想使用其中的代码时,只需要#include"xxx.h"文件即可。传统方式编程:所有的函数均放在main.c中,若使用的模块比较多,则一个文件内会有很多的代码,不利于代码组织和管理,而且很影响编程者的思路。使用LCD602液晶屏作为调试窗口,提供类似printf函数的功能,可实时观察单片机内部数据的变换情况,便于调试和演示。使用到的.h文件必须要放在编译器可寻找到的地方(工程文件夹根目录,安全目录,自定义)

2601_96469072的博客 216

ENSP学习记录(1)

本文分享了在ENSP环境中学习通信、网络通信与数据通信网络的区分心得。通过类比“传话”“用网络传话”“设备系统传话”,厘清三者层级关系;以寄快递比喻封装过程,理解报文结构;反思“报文必有尾部”“网关是设备”等误区,强调概念本质理解的重要性。核心观点:能否举出反例,是检验是否真正掌握的关键。

W20070611的博客 214

Linux网络学习【深入理解多路转接epoll】

本文围绕 Linux 多路转接 epoll 展开,以“设计动机—核心机制—触发模式—代码实践”为主线,对比 select、poll 的监听管理与就绪检查方式,解析关注集合、就绪列表及核心接口,重点讲解水平触发与边缘触发的行为差异,以及边缘触发配合非阻塞读写的处理要点。结合多连接服务器实践,梳理事件注册、连接接收、部分收发、可写事件按需监听及断开清理流程,厘清就绪通知与操作完成的区别,分析常见错误与性能影响因素,帮助读者建立从事件循环到连接管理的完整认识,为高并发服务器与事件驱动框架开发打下基础。

承于所学,探技术之渊;以代码求政,寻成长之道。 1万+

正则表达式学习笔记 02:基础语法

正则表达式是描述字符匹配规则的迷你语言,由普通字符和元字符组成。普通字符直接匹配自身,而元字符如.、*、+、^、$等具有特殊含义,用于控制匹配模式。常见功能包括任意字符匹配、字符类、预定义类(如\d)、量词、位置锚点、分组与捕获、环视断言及反向引用。需注意,若要匹配元字符本身,必须使用转义符\。例如,\.可匹配字面点号。

菜鸟的专栏 150

ES6:Iterator与Generator函数学习及Generator函数和async实现异步编程理解

几个概念:可迭代对象是指具有迭代器接口的对象: 实现类数组使用 for of 循环 对象无法使用数组的迭代器。 generator 函数类似遍历器函数,返回一个迭代器对象; 该对象调用 方法时,会把 后面的表达式作为值 ,并执行当前指针与下一步指针之间的程序。 generator 实现迭代器函数 后面跟的内容为 得到的 值。流程:循环 会调用 generator 函数,返回一个 iterator 对象, 方法由 generator 内部的 决定。 Gene

2403_87566238的博客 212

为什么学习 GUI 程序设计:从 Swing 入门桌面界面开发

学习GUI程序设计能让程序从“能用”走向“好用”,提升用户体验与开发能力。选择Java Swing作为入门,因其随JDK自带、跨平台一致、组件完整且学习曲线平缓。通过掌握容器、组件、布局与事件四大核心概念,结合最小示例实践,可快速构建交互界面。建议循序渐进:运行示例→熟悉组件→理解事件→组合布局→完成小项目(如待办清单),夯实桌面应用开发基础。

xyouyuweizhu的博客 107

echarts学习手记

本文介绍ECharts的引入与基本使用:通过npm安装并按需引入核心模块、图表类型及组件,注册后初始化图表实例。结合resize事件实现响应式布局,通过dispose()销毁实例避免内存泄漏,并支持自定义主题与seriesLayoutBy配置调整数据映射方式,提升图表灵活性与性能。

qq_43592674的博客 38
上一篇: C++全局变量、局部变量、静态全局变量、静态局部变量的区别
下一篇: 生产者消费者模型
Ricky_Theseus
博客等级 码龄3年 126粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ricky_Theseus

感谢大家,祝您生活愉快

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值