精华内容
下载资源
问答
  • 离散数学及其应用

    2019-04-03 22:47:00
    第1章 基础:逻辑和证明 ...第6章 离散概率 第7章 高级计数技术 第8章 关系 第9章 图 第10章 树 第11章 布尔代数 第12章 计算模型 转载于:https://www.cnblogs.com/Two-dimensionalSpace/p...

    第1章  基础:逻辑和证明

    第2章  基本结构:集合、函数、数列与求和

    第3章  基础:算法、整数和矩阵

    第4章  归纳与递归

    第5章  计数

    第6章  离散概率

    第7章  高级计数技术

    第8章  关系

    第9章  图

    第10章  树

    第11章  布尔代数

    第12章  计算模型

    转载于:https://www.cnblogs.com/Two-dimensionalSpace/p/10652216.html

    展开全文
  • 英文版离散数学:Discrete Mathematics and Its Applications 7th Kenneth H.Rosen离散数学及其应用
  • 离散数学及其应用(第六版)离散数学及其应用(第六版)离散数学及其应用(第六版)离散数学及其应用(第六版)
  • 离散数学及其应用.

    2011-10-08 23:24:18
    离散数学及其应用.答案 离散数学及其应用.答案 离散数学及其应用.答案
  • 离散数学及其应用答案 离散数学及其应用答案 离散数学及其应用答案离散数学及其应用答案
  • 关于离散数学非常详细的教辅资料 离散数学及其应用这般书非常适合自学!力荐! 为机器学习以及数学建模都有用处
  • 科研进阶 | 达特茅斯学院 | 计算机科学、数学:离散数学及其应用(7月开课)​mp.weixin.qq.com课题名称 离散数学及其应用开课日期 7月,具体时间待定(名额有限,先到先得~导师介绍 1. 主导师:● 达特茅斯学院...
    科研进阶 | 达特茅斯学院 | 计算机科学、数学:离散数学及其应用(7月开课)mp.weixin.qq.com
    2fc00a00323100071d8655e036bc53d5.png

    课题名称

    离散数学及其应用

    开课日期

    7月,具体时间待定(名额有限,先到先得~

    导师介绍

    1. 主导师:

    达特茅斯学院数学正教授、数学系副主任

    麻省理工学院博士

    累计发表高水平论文50余篇,并于各大国际会议和研讨会演讲100余次

    曾主持组织了代数组合学领域最大的国际会议FPSAC’18

    研究领域:计数组合学及其在动力系统和计算生物学中的应用

    2. 专业助教:

    美国Top10/英国牛剑的博士

    项目收获

    ● 推荐信:保质保量完成任务后,可获得推荐信

    课程证明:导师签发的课程证明

    定制产出:一个基于课程内容的实践项目

    ● 学术经历:符合兴趣的项目制课程学习,开启科研之路

    ● 自我成长:主动解决问题的思维和能力、团队合作能力、提前适应国外的教学模式

    项目详情

    WEEK 1 排列、集合、组合

    (1)有限字母表上单词的计数、排列、有限集合的自己和组合

    (2)掌握二项式系数的基本性质

    (3)理解杨辉三角和二项式定理

    WEEK 2 集合划分、整数划分

    (1)了解集合的分区、整数的分区以及两者之间的区别

    (2)了解整数分区和组合之间的区别

    (3)了解第二类斯特林数和贝尔数

    (4)熟悉欧拉的划分恒等式

    WEEK 3 容斥原理

    (1)掌握并集和交集

    (2)掌握任意数量集合的容斥原理

    (3)欧拉phi函数和满射图

    WEEK 4 递归、生成函数、斐波那契数

    (1)了解如何构建递归来计算离散结构

    (2)熟悉生成函数和形式幂级数

    (3)使用斐波那契数的生成函数来提取系数的公式

    WEEK 5 格路与DNA序列比对

    (1)熟悉反射原理计算具有边界约束的格路工具

    (2)了解如何将DNA序列比对表述为一个组合问题

    WEEK 6 图、生成树和Cayley's公式

    (1)掌握图论中的基本概念,如路径、圈、树

    (2)熟悉欧拉图的特征

    (3)掌握在网络中寻找连接节点最小生成树的算法

    (4)熟悉平面图、四色定理

    WEEK 7 学生项目安排

    (1)深入研究一个有挑战性的组合问题

    (2)了解数学家如何解决问题并提出解决方案

    WEEK 8 学生课堂展示

    本次课会进行学生课堂展示,展示自己的研究成果。

    适合人群

    想要申请计算机科学、数学等相关学科的本科生

    *因为是全英文授课,同学在报名后需要提供雅思或托福英语口语成绩,要求雅思口语不低于6.0分,托福口语不低于19分。若不能提供英语成绩或相应分数,可提供1-3分钟英文视频,主题可选:自我介绍/描述一件最难忘的事。

    项目亮点

    名校导师

    达特茅斯学院正教授课题式授课

    ● 精品小班

    16人以内小班制,保证课程质量

    ● 直播授课

    突破空间限制与导师互动

    ● 班主任关怀

    全天候陪伴帮你解决困难,适应互动式教学

    ● 英文授课

    完美体验海外大学课堂

    常见问题

    1. 推荐信可以用来做什么?

    推荐信是所有留学申请文书中唯一可以作为对申请者学术能力、专业背景等“软实力”做第三方客观评价的文字材料。一封高质量的推荐信能力为留学申请、奖学金申请大大加分,优势甚至可以起到决定性的作用。

    2. 我怎样能获得推荐信?

    进阶Workshop秉持严格的学术独立性,教授出具的推荐信会严格遵守学术体系规则,完全根据学生课堂参与、课后作业、课程项目等表现客观评价提供推荐。所有学员在保质保量按时完成课程任务、没有无故旷课的前提下,都可获得推荐信。

    3. 推荐信会直接交给我吗?

    为了保证真实性与可信性,推荐信不会交与申请者本人,而是以网推形式进行。学生在提交申请时仅提供推荐人的信息(姓名、职位、所在学校学院、邮箱),系统自动发邮件给推荐人,有推荐人自己上传或填写推荐信。

    展开全文
  • 离散数学及其应用第7版偶数答案 离散数学及其应用第7版偶数答案
  • (我当然不会告诉你我其实一开始用的就是蛮力法)好了,进入正题:我们需要找到9个不同的正整数,而且能够尽量节约时间,那么我们可以在《离散数学及其应用》的114页找到“集合的计算机表示”这...

    d1c00f3e4e595e46599e0b6a442f8259.png

    不得不说,计算与探索和计算机课题的难度还是有一定差别的。

    接下来会给出第一章计算与探索中的第1到3题的实现:

    Q1:找出这样的正整数:它不是9个不同的正整数的立方和。

    当然,我们不用蛮力法来解题,手写9层循环也是很累的呀!(我当然不会告诉你我其实一开始用的就是蛮力法)

    好了,进入正题:

    我们需要找到9个不同的正整数,而且能够尽量节约时间,那么我们可以在《离散数学及其应用》的114页找到“集合的计算机表示”这一节,这一节介绍了集合其实可以用二进制位来表示,每个二进制位代表一个元素。

    我们可以发现,假如我们有一个3元素的集合,每一个元素对应的位是否为1,可以表示它是否存在,例如一个集合有元素0、1和2,分别对应二进制位的第0位、第1位和第2位,那么二进制数000表示三个元素都不存在,001表示元素0存在,其他两个都不存在,010代表元素1存在,其他两个不存在,直到111代表三个都存在。那么从000~111的二进制数刚好代表3个元素的集合的所有子集。

    结论:

    n位二进制数的所有表示形式和有n个元素的集合的所有子集是一一对应的关系,并且我们假定对应位为1该元素存在,对应位为0该元素不存在。

    我们知道:n个元素的所有子集数是

    个,n位二进制数能表示所有不同的数也是
    个。

    我们想要从有1到20的所有正整数的集合中找出所有刚好含有9个元素的子集,就可以转换为从20位的二进制数中找到刚好有9个二进制位为1的所有二进制数,那么我们就直接借助计算机的整型数来表示二进制位,遍历从

    的所有二进制数,再从中找到刚好有9个二进制位为1的二进制位串,就可以找到刚好含有9个元素的子集。这个过程完全可以用计算机内置的加法来完成,并且解析的时候可以使用位操作进行解析,不需要更高层次的抽象机制,不会给程序带来很大的负担。

    接下来是源码:

    C++实现:

    #include <iostream>
    #include <fstream>
    #include <set>
    #include <vector>
    #include <string>
    #include <cmath>
    
    using std::vector;
    using std::set;
    using std::string;
    using std::ofstream;
    using std::cout;
    using std::endl;
    
    // 返回x的二进制的1的个数
    inline uint64_t BitCount(uint64_t x)
    {
    	uint64_t sum = 0;
    	uint64_t mask = 0x1111111111111111; // Now mask equals to 0x 1111 1111 1111 1111
    	sum += x & mask;
    	sum += (x >> 1) & mask;
    	sum += (x >> 2) & mask;
    	sum += (x >> 3) & mask;
    	// 4 bits a group
    	mask = 0xffffffff;  // Now mask equals to 0x ffff ffff
    	sum = (sum & mask) + ((sum >> 32) & mask);
    	// 8 bits a group
    	mask = 0x0f0f0f0f;  // Now mask equals to 0x 0f0f 0f0f
    	sum = (sum & mask) + ((sum >> 4) & mask);
    	mask = 0xffff;
    	sum = (sum & mask) + ((sum >> 16) & mask);
    	mask = 0xff;
    	sum = (sum & mask) + ((sum >> 8) & mask);
    	return sum;
    }
    
    // 将数据存储到硬盘中
    template<typename T>
    inline void SaveData(T &numVec, string filename)
    {
    	ofstream txt_Out(filename, ofstream::out | ofstream::trunc);
    	txt_Out << "Size: " << numVec.size() << endl;
    	txt_Out << "Element: " << endl ;
    	for (auto &num : numVec)
    		txt_Out << num << endl;
    	txt_Out.close();
    }
    /* 求出不可重复的正整数集合次幂和,返回值为存有这些数的集合
     * pow表示需要求的整数的幂次数,cntBitSet表示每次有几个数参与运算,maxCandiNum表示候选数的最大值,也就是集合的元素个数,程序使用的64位的无符号数,所以不能超过64位
     */
    set<uint64_t> NonRepeatedPosiIntPowerSum(const uint32_t powNum, const uint32_t cntBitSet, const uint32_t maxCandiNum)
    {
    	// maxBitSet是循环的次数,maxBitSet的值等于2^n,
    	// numOne是辅助移位变量,字面值1编译器默认认为它为32位数
    	const uint64_t numOne = 1;
    	const uint64_t maxBitSet = numOne << maxCandiNum;
    	// allNumVec存放所有满足条件的数字,由于数字量很大,首先分配一些内存提高程序性能
    	vector<uint64_t> allNumVec;
    	allNumVec.reserve(200000);
    
    	// 用 bitSet的二进制位串表示一个集合,最低位表示数字元素1,最高位表示数字元素64,防止出现算术移位,所以使用无符号类型 
    	// 二进制位为1代表存在该数字元素,为0代表不存在,00101代表存在数字1和3,并且2、3和4不存在 
    	for (uint64_t bitSet = 0; bitSet != maxBitSet + 1; ++bitSet)
    	{
    		// 如果位串的1个数不为cntBitSet个,那么跳过本次循环 
    		if (BitCount(bitSet) != cntBitSet)
    			continue;
    		// 用numVec保存本次循环被选出的9个元素
    		vector<uint32_t> numVec;
    		numVec.reserve(cntBitSet);
    		// bit_loc 代表现在处理的是哪个位置的二进制位,但是对应的数字是bit_loc+1 
    		for (uint32_t bit_loc = 0; bit_loc != maxCandiNum; ++bit_loc)
    			// 通过位运算筛选出本次循环的9个数字元素,存放到numArray中
    			if ((bitSet >> bit_loc & 1) == 1)
    				numVec.push_back(bit_loc + 1);
    		uint64_t sum = 0;
    		for (const uint32_t &num : numVec)
    			sum += pow(num, powNum);
    		allNumVec.push_back(sum);
    	}
    
    	
    
    	// 由于数值很可能存在重复,所以定义集合来保存唯一的数值,并且按照升序排序
    	set<uint64_t> setAllNum;
    	for (const uint64_t &num : allNumVec)
    		setAllNum.insert(num);
    	return setAllNum;
    }
    
    int main()
    {
    	// pow表示需要求的整数的幂次数
    	const uint32_t powNum = 3;
    	// cntBitSet表示每次有几个数参与运算 
    	const uint32_t cntBitSet = 9;
    	// maxCandiNum表示候选数的最大值,也就是集合的元素个数,程序使用的64位的无符号数,所以不能超过64位
    	const uint32_t maxCandiNum = 30;
    	
    	set<uint64_t> setAllNum;
    	setAllNum = NonRepeatedPosiIntPowerSum(powNum, cntBitSet, maxCandiNum);
    
    	// 找出setAllNum的最大值
    	uint64_t maxNum = 0;
    	for (const uint64_t &num : setAllNum)
    		if (num > maxNum)
    			maxNum = num;
    
    	cout << "1~" << maxNum << "范围内是" << cntBitSet << "个正整数的" << powNum << "次方和的数一共有:" << setAllNum.size() << "个" << endl;
    
    	// otherNumVec存放所有不满足条件的数字
    	vector<uint64_t> otherNumVec;
    	otherNumVec.reserve(200000);
    
    	uint32_t cnt = 0;
    	for (uint32_t num = 1; num != maxNum + 1; ++num)
    	{
    		// 如果遇到满足条件的元素就跳过,count会返回该数值的个数,为1就跳过本次循环
    		if (setAllNum.count(num))
    			continue;
    		otherNumVec.push_back(num);
    	}
    	cout << "1~" << maxNum << "范围内是" << cntBitSet << "个正整数的" << powNum << "次方和的数一共有:" << otherNumVec.size() << "个" << endl;
    
    	string path = "是" + std::to_string(cntBitSet) + "个数的" + std::to_string(powNum) + "次方和的数.txt";
    	cout << path << endl;
    	SaveData(setAllNum, path);
    	path = "不是" + std::to_string(cntBitSet) + "个数的" + std::to_string(powNum) + "次方和的数.txt";
    	cout << path << endl;
    	SaveData(otherNumVec, path);
    
    	return 0;
    }
    

    里面的BitCount函数的实现可以自己用一个例子代入尝试一下整个算法流程就可以很好的理解啦。

    Q2:找出大于79的正整数:它不是18个正整数的四次幂的和。

    这次的要求的是18个正整数,也就是可以存在重复的情况,18个数用蛮力法就更不行啦。

    那这一题可以用整型数的二进制位串来做吗?当然可以,首先请大家看《离散数学及其应用》第358页中“有重复的组合”这一节,介绍了有重复的组合是如何表示的,是如何计算的,作者写得很好,我就不搬运了,请大家看完之后再看下面。

    我们现在知道了,要求解n个元素的集合的可重复的r组合数,就是n-1个分隔栏和r个元素的组合数,那我们就把二进制位串中的1当作分隔栏,0当作存在的元素(当然反过来也可以的),按照之前的思路,我们如果想从20个元素的集合中找出可以重复的10个元素的组合,这时候至少需要20-1+10=29位二进制位来表示,我们就遍历从0到

    的所有数,找出其中二进制位为1个数为20-1=19个的所有数,就可以找出所有20个元素的集合的可重复的10组合的表示。这个过程和上一题类似,只需要每次对整型数加1,并且用位操作进行解析就可以完成。

    接下来是源码:

    C++实现:

    #include <iostream>
    #include <fstream>
    #include <set>
    #include <vector>
    #include <string>
    #include <cmath>
    
    using std::vector;
    using std::set;
    using std::string;
    using std::ofstream;
    using std::cout;
    using std::endl;
    
    /* 可以借鉴1.1的思想,将可以重复的组合仍然映射为位串,由于可以n元素可以重复的组合r组合可以看作,r个元素和n-1个栅栏的组合,就把r个元素当作0,把n-1个栅栏当作1,
     * 反过来也可以,再用BitCount就可以,就需要改一下解析的部分,把1看作分隔栏,最右边的1是1和2的分隔栏,它右边的1的是2和3的分隔栏,看它们中间有多少个1就可以知道
     * 相应位置(例如数字1)有多少个了,然后就可以了。
     */
    
    
    // 返回x的二进制的1的个数
    inline uint64_t BitCount(uint64_t x)
    {
    	uint64_t sum = 0;
    	uint64_t mask = 0x1111111111111111; // Now mask equals to 0x 1111 1111 1111 1111
    	sum += x & mask;
    	sum += (x >> 1) & mask;
    	sum += (x >> 2) & mask;
    	sum += (x >> 3) & mask;
    	// 4 bits a group
    	mask = 0xffffffff;  // Now mask equals to 0x ffff ffff
    	sum = (sum & mask) + ((sum >> 32) & mask);
    	// 8 bits a group
    	mask = 0x0f0f0f0f;  // Now mask equals to 0x 0f0f 0f0f
    	sum = (sum & mask) + ((sum >> 4) & mask);
    	mask = 0xffff;
    	sum = (sum & mask) + ((sum >> 16) & mask);
    	mask = 0xff;
    	sum = (sum & mask) + ((sum >> 8) & mask);
    	return sum;
    }
    
    // 将数据存储到硬盘中
    template<typename T>
    inline void SaveData(T &numVec, string filename)
    {
    	ofstream txt_Out(filename, ofstream::out | ofstream::trunc);
    	txt_Out << "Size: " << numVec.size() << endl;
    	txt_Out << "Element: " << endl;
    	for (auto &num : numVec)
    		txt_Out << num << endl;
    	txt_Out.close();
    }
    
    /* 求出可重复的正整数集合次幂和,返回值为存有这些数的集合
     * pow表示需要求的整数的幂次数,cntBitSet表示每次有几个数参与运算,maxCandiNum表示候选数的最大值,也就是集合的元素个数,程序使用的64位的无符号数,所以不能超过64位
     */
    set<uint64_t> RepeatedPosiIntPowerSum(const uint32_t powNum, const uint32_t cntBitSet, const uint32_t maxCandiNum)
    {
    	// 计算每次需要用到多少二进制位
    	// 由于n个元素集合可以重复的的r组合一共需要用maxCandiNum-1+cntBitSet位来表示,程序使用的64位的无符号数,所以这个和不能超过64位
    	const uint32_t maxBitNum = maxCandiNum - 1 + cntBitSet;
    	// maxBitSet是循环的次数,maxBitSet的值等于2^maxBitNum,因为遍历的是1到2^maxBitNum-1的二进制位,就可以找到所有满足条件的集合
    	// numOne是辅助移位变量,字面值1编译器默认认为它为32位数
    	const uint64_t numOne = 1;
    	const uint64_t maxBitSet = numOne << maxBitNum;
    	// allNumVec存放所有满足条件的数字,由于数字量很大,首先分配一些内存提高程序性能
    	vector<uint64_t> allNumVec;
    	allNumVec.reserve(200000);
    
    	// 用 bitSet的二进制位串表示一个集合,最低位表示数字元素1,最高位表示数字元素64,防止出现算术移位,所以使用无符号类型 
    	// 二进制位为1代表分隔栏,为0代表存在数字
    	for (uint64_t bitSet = 0; bitSet != maxBitSet + 1; ++bitSet)
    	{
    		// 如果位串的1个数不为maxCandiNum - 1个(即位串代表分隔的1数不合适,1代表所有候选数中的分隔栏),那么跳过本次循环 
    		if (BitCount(bitSet) != maxCandiNum - 1)
    			continue;
    		// 用 numVec保存本次循环的位串中,maxCandiNum个元素(从1~maxCandiNum)的每个元素有几个,假如numVec[0]=1,那么数字元素1就有一个,并且初始化其全为0
    		vector<uint64_t> numVec(maxCandiNum,0);
    		// 保存当前在处理1~cntBitSet中的哪个数字,0代表数字元素1,1代表数字元素2,类推
    		uint32_t numProcessing = 0;
    		for (uint32_t cntBit = 0; cntBit != maxBitNum; ++cntBit)
    		{
    			// 当第cntBit位为1时,即需要变化处理的数字位
    			if ((bitSet >> cntBit & 1))
    				++numProcessing;
    			// 当第cntBit位为0时,该位串中的第numProcessing个数字相应的元素的总数就加1
    			else
    				++numVec.at(numProcessing);
    		}
    		uint64_t sum = 0;
    		for (uint32_t num = 1; num != maxCandiNum + 1; ++num)
    			sum += static_cast<uint64_t>(numVec.at(num - 1) * pow(num, powNum));
    		allNumVec.push_back(sum);
    	}
    	// 由于数值很可能存在重复,所以定义集合来保存唯一的数值,并且按照升序排序
    	set<uint64_t> setAllNum;
    	for (const uint64_t &num : allNumVec)
    		setAllNum.insert(num);
    	return setAllNum;
    }
    
    int main()
    {
    	// pow表示需要求的整数的幂次数
    	const uint32_t powNum = 4;
    	// cntBitSet表示每次有几个数参与运算 
    	const uint32_t cntBitSet = 18;
    	// maxCandiNum表示候选数的最大值,也就是集合的元素个数
    	const uint32_t maxCandiNum = 10;
    	
    	set<uint64_t> setAllNum;
    	setAllNum = RepeatedPosiIntPowerSum(powNum, cntBitSet, maxCandiNum);
    
    	// 找出setAllNum的最大值
    	uint64_t maxNum = 0;
    	for (const uint64_t &num : setAllNum)
    		if (num > maxNum)
    			maxNum = num;
    	cout << "1~" << maxNum << "范围内是" << cntBitSet <<"个正整数的" << powNum << "次方和的数一共有:" << setAllNum.size() << "个" << endl;
    
    	// allNumNeededVec存放所有不满足条件的数字
    	vector<uint64_t> otherNumVec;
    	otherNumVec.reserve(200000);
    
    	uint32_t cnt = 0;
    	for (uint64_t num = 1; num != maxNum + 1; ++num)
    	{
    		// 如果遇到满足条件的元素就跳过,count会返回该数值的个数,为1就跳过本次循环
    		if (setAllNum.count(num))
    			continue;
    		otherNumVec.push_back(num);
    	}
    	cout << "1~" << maxNum << "范围内是" << cntBitSet << "个正整数的" << powNum << "次方和的数一共有:" << otherNumVec.size() << "个" << endl;
    
    	string path = "是" + std::to_string(cntBitSet) + "个数的" + std::to_string(powNum) + "次方和的数.txt";
    	cout << path << endl;
    	SaveData(setAllNum, path);
    	path = "不是" + std::to_string(cntBitSet) + "个数的" + std::to_string(powNum) + "次方和的数.txt";
    	cout << path << endl;
    	SaveData(otherNumVec, path);
    
    	return 0;
    }
    

    Q3:找出尽可能多的正整数:它可以用两种不同的方式写成正整数的立方和,1729就具有这个性质。

    这一题和第二题类似,是可以重复的情况,那么我们就可以调用第二题的封装好的函数就可以做这一题啦。在第三题实现的时候我稍微改了一下那个函数,便于后面查重,大家就看代码好啦!

    接下来是源码:
    C++实现:

    #include <iostream>
    #include <fstream>
    #include <set>
    #include <vector>
    #include <string>
    #include <algorithm>
    #include <cmath>
    
    using std::vector;
    using std::sort;
    using std::set;
    using std::string;
    using std::ofstream;
    using std::cout;
    using std::endl;
    
    // 返回x的二进制的1的个数
    inline uint64_t BitCount(uint64_t x)
    {
    	uint64_t sum = 0;
    	uint64_t mask = 0x1111111111111111; // Now mask equals to 0x 1111 1111 1111 1111
    	sum += x & mask;
    	sum += (x >> 1) & mask;
    	sum += (x >> 2) & mask;
    	sum += (x >> 3) & mask;
    	// 4 bits a group
    	mask = 0xffffffff;  // Now mask equals to 0x ffff ffff
    	sum = (sum & mask) + ((sum >> 32) & mask);
    	// 8 bits a group
    	mask = 0x0f0f0f0f;  // Now mask equals to 0x 0f0f 0f0f
    	sum = (sum & mask) + ((sum >> 4) & mask);
    	mask = 0xffff;
    	sum = (sum & mask) + ((sum >> 16) & mask);
    	mask = 0xff;
    	sum = (sum & mask) + ((sum >> 8) & mask);
    	return sum;
    }
    
    // 将数据存储到硬盘中
    template<typename T>
    inline void SaveData(T &numVec, string filename)
    {
    	ofstream txt_Out(filename, ofstream::out | ofstream::trunc);
    	txt_Out << "Size: " << numVec.size() << endl;
    	txt_Out << "Element: " << endl;
    	for (auto &num : numVec)
    		txt_Out << num << endl;
    	txt_Out.close();
    }
    
    /* 求出可重复的正整数集合次幂和,返回值为存有这些数的向量
     * pow表示需要求的整数的幂次数,cntBitSet表示每次有几个数参与运算,maxCandiNum表示候选数的最大值,也就是集合的元素个数,程序使用的64位的无符号数,所以不能超过64位
     */
    vector<uint64_t> RepeatedPosiIntPowerSum(const uint32_t powNum, const uint32_t cntBitSet, const uint32_t maxCandiNum)
    {
    	// 计算每次需要用到多少二进制位
    	// 由于n个元素集合可以重复的的r组合一共需要用maxCandiNum-1+cntBitSet位来表示,程序使用的64位的无符号数,所以这个和不能超过64位
    	const uint32_t maxBitNum = maxCandiNum - 1 + cntBitSet;
    	// maxBitSet是循环的次数,maxBitSet的值等于2^maxBitNum,因为遍历的是1到2^maxBitNum-1的二进制位,就可以找到所有满足条件的集合
    	// numOne是辅助移位变量,字面值1编译器默认认为它为32位数
    	const uint64_t numOne = 1;
    	const uint64_t maxBitSet = numOne << maxBitNum;
    	// allNumVec存放所有满足条件的数字,由于数字量很大,首先分配一些内存提高程序性能
    	vector<uint64_t> allNumVec;
    	allNumVec.reserve(200000);
    
    	// 用 bitSet的二进制位串表示一个集合,最低位表示数字元素1,最高位表示数字元素64,防止出现算术移位,所以使用无符号类型 
    	// 二进制位为1代表分隔栏,为0代表存在数字
    	for (uint64_t bitSet = 0; bitSet != maxBitSet + 1; ++bitSet)
    	{
    		// 如果位串的1个数不为maxCandiNum - 1个(即位串代表分隔的1数不合适),那么跳过本次循环 
    		if (BitCount(bitSet) != maxCandiNum - 1)
    			continue;
    		// 用 numVec保存本次循环的位串中,maxCandiNum个元素(从1~maxCandiNum)的每个元素有几个,假如numVec[0]=1,那么数字元素1就有一个,并且初始化其全为0
    		vector<uint64_t> numVec(maxCandiNum, 0);
    		// 保存当前在处理1~cntBitSet中的哪个数字,0代表数字元素1,1代表数字元素2,类推
    		uint32_t numProcessing = 0;
    		for (uint32_t cntBit = 0; cntBit != maxBitNum; ++cntBit)
    		{
    			// 当第cntBit位为1时,即需要变化处理的数字位
    			if ((bitSet >> cntBit & 1))
    				++numProcessing;
    			// 当第cntBit位为0时,该位串中的第numProcessing个数字相应的元素的总数就加1
    			else
    				++numVec.at(numProcessing);
    		}
    		uint64_t sum = 0;
    		for (uint32_t num = 1; num != maxCandiNum + 1; ++num)
    			sum += static_cast<uint64_t>(numVec.at(num - 1) * pow(num, powNum));
    		allNumVec.push_back(sum);
    	}
    
    	sort(allNumVec.begin(), allNumVec.end());
    
    	return allNumVec;
    }
    int main()
    {
    	// pow表示需要求的整数的幂次数
    	const uint32_t powNum = 3;
    	// maxCandiNum表示候选数的最大值,也就是集合的元素个数
    	const uint32_t maxCandiNum = 30;
    
    	vector<uint64_t> numVec(RepeatedPosiIntPowerSum(powNum, 2, maxCandiNum));
    	vector<uint64_t> neededNum;
    	vector<uint64_t> testVec;
    	testVec.reserve(numVec.size());
    	set<uint64_t> numSet;
    	uint32_t cnt = 0;
    	for (uint32_t i = 0; i != numVec.size(); ++i)
    	{
    		uint64_t num = numVec.at(i);
    		numSet.insert(num);
    		testVec.push_back(num);
    		if (numSet.size() + cnt != testVec.size())
    		{
    			neededNum.push_back(numVec.at(i));
    			++cnt;
    		}
    	}
    	cout << cnt << "个" << endl;
    	for (const uint64_t &num : neededNum)
    		cout << num << endl;
    	return 0;
    }
    

    文章来源:

    《离散数学及其应用》第一章 计算与探索 - Ace C Lee 个人网站aceclee.com

    对计算机科学或者日语感兴趣的同学可以访问我的网站,里面有很多计算机和日语相关的干货哦!

    Ace C Lee 个人网站 - 我的个人网站aceclee.com
    展开全文
  • 离散数学及其应用第六版英文偶数提答案,离散数学书作者Kenneth H.Rosen
  • 离散数学及其应用习题解析离散数学及其应用习题解析离散数学及其应用习题解析离散数学及其应用习题解析离散数学及其应用习题解析离散数学及其应用习题解析
  • 离散数学 离散数学及其应用 PDF电子书 数学学习资料 离散数学 离散数学及其应用 PDF电子书 数学学习资料
  • 离散数学及其应用(英文版)(第7版)》是介绍离散数学理论和方法的经典教材,已经成为采用率最高的离散数学教材,被美国众多名校用作教材,获得了极大的成功。《离散数学及其应用(英文版)(第7版)》中文版也已...
  • 离散数学及其应用第7版 奇数题答案
  • 离散数学及其应用,国外经典教材,Kenneth H Rosen 大作 离散数学学习最佳教材
  • 离散数学及其应用第6版中文版 罗森著 离散数学及其应用第6版中文版 罗森著
  • 离散数学及其应用,英文第七版,注释版。 作者Kenneth H. Rosen
  • 离散数学及其应用,Discrete Mathematics and Its Applications
  • 离散数学及其应用第八版偶数题答案(英文
  • 离散数学及其应用(第7版) .
  • 离散数学及其应用 原书第7版 高清目录 pdf 电子书
  • 离散数学及其应用第七版习题答案.zip
  • 此文档是离散数学及其应用第六版的配套答案,有助于完成离散数学及其应用第六版课本后配套练习。
  • 离散数学及其应用(原书第6版)》是经典的离散数学教材,为全球多所大学广为采用。《离散数学及其应用(原书第6版)》全面而系统地介绍了离散数学的理论和方法,内容涉及数学推理、组合分析、离散结构、算法思维以及...
  • 离散数学及其应用附部分习题和答案
  • 离散数学及其应用英文版·第7版奇数答案
  • 离散数学及其应用7 奇数题答案.zip
  • 离散数学及其应用7 偶数题答案.zip

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 878
精华内容 351
关键字:

离散数学及其应用