第十四届蓝桥杯大赛软件赛省赛-试题 B---01 串的熵 解题思路+完整代码

news/2024/11/20 0:33:29/

欢迎访问个人网站来查看此文章:http://www.ghost-him.com/posts/db23c395/

问题描述

对于一个长度为 n 的 01 串 S=x1x2x3...xnS = x_{1} x_{2} x_{3} ... x_{n}S=x1x2x3...xn,香农信息熵的定义为 H(S)=−∑1np(xi)log2(p(xi))H(S ) = − {\textstyle \sum_{1}^{n}} p(x_{i})log_{2} (p(x_{i}))H(S)=1np(xi)log2(p(xi)),其中 p(0)p(0)p(0), p (1)(1)(1) 表示在这个 010101 串中 000111 出现的占比。比如,对于 S=100S = 100S=100 来说,信息熵 H(S)=−13log2(13)−23log2(23)−23log2(23)=1.3083H(S ) = − \frac{1}{3} log_{2} ( \frac{1}{3} ) − \frac{2}{3} log_{2}( \frac{2}{3} ) − \frac{2}{3} log_{2} ( \frac{2}{3} ) = 1.3083H(S)=31log2(31)32log2(32)32log2(32)=1.3083。对于一个长度为 233333332333333323333333010101 串,如果其信息熵为 11625907.579811625907.579811625907.5798,且 000 出现次数比 111 少,那么这个 010101 串中 000 出现了多少次?

思路

我们先来看这个 h(s)h(s)h(s) 的定义,然后先把 h(s)h(s)h(s) 这个函数写出来。

我们看这个 100100100 的例子:一共有 1 个 1,2 个 0,h(s)h(s)h(s) 也是由 1 个 −13log2(13)− \frac{1}{3} log_{2} ( \frac{1}{3} )31log2(31) 和 2 个 −23log2(23)− \frac{2}{3} log_{2}( \frac{2}{3} )32log2(32) 构成,再根据公式,我们可以推测:如果有 n 个 0,m 个 1,那么 h(s)h(s)h(s) 应该是由 n 个 p(0)log2(p(0))p(0)log_{2}(p(0))p(0)log2(p(0)) 构成,同时,由 m 个 p(1)log2(p(1))p(1)log_{2}(p(1))p(1)log2(p(1)) 构成。p(0)p(0)p(0) 表示 0 出现的占比,p(0)=nn+mp(0) = \frac{n}{n + m}p(0)=n+mnp(1)=mn+mp(1) = \frac{m}{n + m}p(1)=n+mm。所以我们可以设一个函数,用来求解 h(s)h (s)h(s)

#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;int gcd(int a, int b) {return b ? gcd(b, a % b) : a;
}// p0 表示 '0' 出现的次数;p1表示 '1' 出现的次数
double h(int p0, int p1) {// 需要将 3/6 化简成 1/2 这样的形式,简化运算的时间// 将分子和分母共同除以它们的最大公因数即可。int t0 = p0, t1 = p1;// 获取最大公因数int t = gcd(t0, t1);// 化简t0 /= t, t1 /= t;// 获取总数double t2 = t0 + t1;// 返回的答案double res = 0;// 套入公式res -= p0 * (t0 / t2) * (log2(t0) - log2(t2));res -= p1 * (t1 / t2) * (log2(t1) - log2(t2));return res;
}int main () {// 100 由 2个0 和 1个1 组成,代入函数以验证函数的正确性cout << h(2, 1) << endl;return 0;
}

可得运行结果:

1.30827

与题目中的结果一致,说明我们写的代码是正确的。

接下来我们就应该来求这个题目的答案了。

我们先来看看这个函数的性质:我们多求几组数字。我们以长度为 10 的所有 01 串来看:

int main () {cout << h(9, 1) << endl;cout << h(8, 2) << endl;cout << h(7, 3) << endl;cout << h(6, 4) << endl;cout << h(5, 5) << endl;cout << h(4, 6) << endl;cout << h(3, 7) << endl;cout << h(2, 8) << endl;cout << h(1, 9) << endl;return 0;
}

可得运行结果:

1.56342
2.98911
4.08468
4.76816
5
4.76816
4.08468
2.98911
1.56342

我们可以发现:

  1. h(s)h(s)h(s) 关于 5 对称
  2. 在对称轴的一侧,h(s)h(s)h(s) 的值单调

由于题目中说明:且 0 出现次数比 1 少 ,所以,0 的个数一定小于总数的一半,所以 0 的数量越多,熵越大。我们知道了这个性质以后,可以采用二分的方法,将 0 的数量二分出来。

int main () {// 0 的数量最小是 1, 最大是 (23333333 + 1) / 2 (总数的一半)int l = 1, r = (23333333 + 1) / 2;while (l < r) {// 获取当前判断的 0 的数量int mid = l + r >> 1;// 如果熵大于目标值,说明 0 的数量太多了,要减小 0 的数量// 如果熵小于目标值,说明 0 的数量太少了,要增加 0 的数量if (h(mid, 23333333 - mid) > 11625907.5798) r = mid; // 减少 0else l = mid + 1; // 增加 0}cout << l << endl;return 0;
}

可得:

11027421

然后我们再验证一下这个结果:

int main () {printf("%.10lf", h(11027421, 23333333 - 11027421));return 0;
}

得结果:

11625907.5798144601

正确

答案

11027421

完整的代码

#include <iostream>
#include <cstring>
#include <algorithm>using namespace std;int gcd(int a, int b) {return b ? gcd(b, a % b) : a;
}double h(int p0, int p1) {int t0 = p0, t1 = p1;int t = gcd(t0, t1);t0 /= t, t1 /= t;double t2 = t0 + t1;double res = 0;res -= p0 * (t0 / t2) * (log2(t0) - log2(t2));res -= p1 * (t1 / t2) * (log2(t1) - log2(t2));return res;
}int main () {int l = 1, r = (23333333 + 1) / 2;while (l < r) {int mid = l + r >> 1;if (h(mid, 23333333 - mid) > 11625907.5798) r = mid;else l = mid + 1;}cout << l << endl;return 0;
}

http://www.ppmy.cn/news/40937.html

相关文章

web自动化测试入门篇06 —— 元素定位进阶技巧

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;【Austin_zhai】 &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xff0c;分享行业相关最新信息。…

场景联动设备触发消息设计思考

场景联动设备触发消息设计思考 一&#xff1a;数据丢失。 消息是否会发生丢失&#xff0c;在于以下 3 个环节&#xff1a; 1、生产者会不会丢消息&#xff1f; 2、消费者会不会丢消息&#xff1f; 3、队列中间件会不会丢消息&#xff1f; 生产者会不会丢消息&#xff1f;…

什么是事务,了解事务的隔离级别和传播行为

一、什么是事务&#xff1f; 事务&#xff08;Transaction&#xff09;是访问并可能更新数据库中各项数据项的一个程序执行单元&#xff08;unit&#xff09;。 事务由事务开始&#xff08;begin transaction&#xff09;和事务结束&#xff08;end transaction&#xff09;之间…

行为型模式-责任链模式

行为型模式-责任链模式 责任链模式(Chain of Responsibility)解决请求处理问题描述适用环境优点:缺点:违反原则:代码实现责任链模式(Chain of Responsibility) 解决请求处理问题 描述 通过将多个对象组成一条处理链来依次处理请求,从而使得请求能够被动态地转发和处…

头歌(Linux之进程管理一):第2关:进程创建操作-fork

任务描述 在上一关我们学习如何获取进程的pid信息&#xff0c;本关我们将介绍如何编程创建一个新的进程。 本关任务&#xff1a;学会使用C语言在Linux系统中使用fork系统调用创建一个新的进程。 相关知识 在Linux系统中创建进程有很多函数可以使用&#xff0c;其中包括了系…

银行数字化转型导师坚鹏:城商行数字化转型案例研究

城商行数字化转型案例研究课程背景&#xff1a; 很多银行存在以下问题&#xff1a;不清楚城商行数字化转型能否成功&#xff1f;不知道其它城商行数字化转型的成功做法&#xff1f;不知道其它标杆城商行的数字化转型战略&#xff1f; 课程特色&#xff1a;用实战案例解…

个人练习-Leetcode-1588. Sum of All Odd Length Subarrays

题目链接&#xff1a;https://leetcode.cn/problems/sum-of-all-odd-length-subarrays/ 题目大意&#xff1a;给出一个数组&#xff0c;求其中所有长度为奇数的子列的所有元素和。 思路&#xff1a;虽然写着是简单题&#xff08;暴力做可以通过&#xff09;&#xff0c;但一看…

看懂体操 - 1. 通识

目录基本规则基本动作基本规则 ㊀ 女子体操共分为 6 个项目&#xff1a; ① 团体 (TQ 团体预赛 、TF 团体决赛&#xff09; 团体总分前 8 名进入 TF ② 个人全能 (AA 个人全能决赛&#xff09; 4 项总分前 24 名进入 AA ③ 4 个单项 (EF 单项决赛)&#xff1a; ❶ 自由操 (FX)…