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

这篇具有很好参考价值的文章主要介绍了第十四届蓝桥杯大赛软件赛省赛-试题 B---01 串的熵 解题思路+完整代码。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

问题描述

对于一个长度为 n 的 01 串 S = x 1 x 2 x 3 . . . x n S = x_{1} x_{2} x_{3} ... x_{n} S=x1x2x3...xn,香农信息熵的定义为 H ( S ) = − ∑ 1 n p ( x i ) l o g 2 ( p ( x i ) ) 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) 表示在这个 01 01 01 串中 0 0 0 1 1 1 出现的占比。比如,对于 S = 100 S = 100 S=100 来说,信息熵 H ( S ) = − 1 3 l o g 2 ( 1 3 ) − 2 3 l o g 2 ( 2 3 ) − 2 3 l o g 2 ( 2 3 ) = 1.3083 H(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.3083 H(S)=31log2(31)32log2(32)32log2(32)=1.3083。对于一个长度为 23333333 23333333 23333333 01 01 01 串,如果其信息熵为 11625907.5798 11625907.5798 11625907.5798,且 0 0 0 出现次数比 1 1 1 少,那么这个 01 01 01 串中 0 0 0 出现了多少次?

思路

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

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

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

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; // 减少 0
		else l = mid + 1; // 增加 0
	}
	cout << l << endl;
	return 0;
}

可得:

11027421

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

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

得结果:

11625907.5798144601

正确文章来源地址https://www.toymoban.com/news/detail-409187.html

答案

11027421

完整的代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

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;
}

到了这里,关于第十四届蓝桥杯大赛软件赛省赛-试题 B---01 串的熵 解题思路+完整代码的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第十四届蓝桥杯大赛软件赛省赛 Java 大学 B 组题解

    找规律,可以先手动模拟几次,会发现 随着n越大,零也越多,当n为40的时候刚好有9个0 所以到40项以后的末尾9个阶乘的和一定是不变的,可以用手算,也可以写程序 答案是,901327897 代码: Java中有十进制转化为二进制,十六进制,八进制的方法,暴力枚举一下即可。(因为

    2024年02月02日
    浏览(44)
  • 第十四届蓝桥杯大赛软件赛省赛(C/C++ 研究生组)

    蓝桥杯 2023年省赛真题 C/C++ 大学G组  试题 A: 工作时长  试题 B: 与或异或  试题 C: 翻转  试题 D: 阶乘的和  试题 E: 公因数匹配  试题 F: 奇怪的数  试题 G: 太阳  试题 H: 子树的大小  试题  I: 高塔  试题 J: 反异或 01 串 除去第 F rm F F 题,其他题目在其他组别都有出

    2024年02月08日
    浏览(50)
  • 第十四届蓝桥杯大赛软件赛省赛(C/C++ 大学A组)

    本题总分: 5 5 5 分 【问题描述】   小蓝认为如果一个数含有偶数个数位,并且前面一半的数位之和等于后面一半的数位之和,则这个数是他的幸运数字。例如 2314 2314 2314 是一个幸运数字,因为它有 4 4 4 个数位,并且 2 + 3 = 1 + 4 2 + 3 = 1 + 4 2 + 3 = 1 + 4 。现在请你帮他计算从

    2024年02月05日
    浏览(54)
  • 第十四届蓝桥杯大赛软件赛省赛(C/C++ 大学C组)

    本题总分: 5 5 5 分 【问题描述】   求 1 1 1 (含)至 20230408 20230408 20230408 (含)中每个数的和。 【答案提交】   这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。 2046347140384

    2024年02月04日
    浏览(48)
  • 第十四届蓝桥杯大赛软件赛省赛 C/C++ 大学 B 组

    注意!!!!!!!!!!这篇题解为赛时的个人做法,不代表是正确的,仅供参考。 更新:思路上应该都对,很多题都有细节错误,代码不用看了,太久没敲代码了(- -) 更新2:代码除了岛屿的都改好了,整数删除常数有点大,可能会t,赛时的代码一堆错误,还是对自己的文

    2024年02月05日
    浏览(43)
  • 第十四届蓝桥杯大赛软件赛省赛(C/C++ 大学B组)

    目前除 B、F题未补,其余题均已更完,经非官方数据测试均可AC。欢迎交流   小蓝现在有一个长度为 100 的数组,数组中的每个元素的值都在 0 到 9 的 范围之内。数组中的元素从左至右如下所示: 5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0

    2024年02月02日
    浏览(47)
  • 第十四届蓝桥杯大赛软件赛省赛 C/C++ 大学 A 组 C题

    输入一行包含两个整数 L, R,用一个空格分隔。 输出一行包含一个整数满足题目给定条件的 x 的数量。 1 5 4 对于 40% 的评测用例,L R ≤ 5000 ; 对于所有评测用例,1 ≤ L ≤ R ≤ 10^9 。 暴力没说的,y肯定在l-r之间。同时要想到x=(y+z)(y-z)那么x就只能是y+z的倍数。 1.使用了

    2023年04月15日
    浏览(97)
  • 第十四届蓝桥杯大赛软件赛省赛 C/C++ 大学 A 组 D题

    输入一行包含一个长度为 n 的字符串表示 num(仅包含数字字符 0 ∼ 9), 从左至右下标依次为 0 ∼ n − 1。 输出一行包含一个整数表示答案。 210102 8一共有 8 种不同的方案: 1)所选择的子串下标为 0 ∼ 1 ,反转后的 numnew = 120102 210102 ; 2)所选择的子串下标为 0 ∼ 2 ,反转

    2023年04月11日
    浏览(40)
  • 第十四届蓝桥杯大赛青少年省赛C++组试题真题 2023年5月

    一、选择题 第 1 题 单选题 C++中,bool类型的变量占用字节数为 ( )。 A. 1 B. 2 C. 3 D. 4 第 2 题 单选题 以下关于C++结构体的说法,正确的是 ( )。 A. 结构体中只能包含成员变量,不能包含成员函数 B. 结构体不能从另一个结构体继承 C. 结构体里面可以包含静态成员变量 D. 结构体里

    2024年02月15日
    浏览(54)
  • 第十四届蓝桥杯大赛软件组省赛 Python大学A组 个人暴力题解

    4.23 update: 省一咯 Powered by: NEFU AB-IN 博主个人的暴力题解,基本很少是正解,求轻喷 题意 思路 模拟即可,本身想用Python自带的datetime库,结果发现年不能开那么大,就直接手写了 代码 题意 思路 DFS爆搜即可 代码 题意 思路 直接没思路,一看到数据范围瞬间怂了,脑子里想的

    2023年04月09日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包