《趣题学算法》—第1章1.3节加法原理和乘法原理

简介:

本节书摘来自异步社区《趣题学算法》一书中的第1章1.3节加法原理和乘法原理,作者徐子珊,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.3 加法原理和乘法原理
组合数学中有两条著名的原理——加法原理和乘法原理。利用这两条原理可以快速地解决一些计数问题。

加法原理:做一件事,完成它可以有n类办法,在第一类办法中有m1种不同的方法,在第二类办法中有m2种不同的方法,……,在第n类办法中有mn种不同的方法,那么完成这件事共有N=m1+m2+m3+…+mn种不同方法。

乘法原理:做一件事,完成它需要分成n个步骤,做第一步有m1种不同的方法,做第二步有m2种不同的方法,……,做第n步有mn种不同的方法,那么完成这件事共有N=m1×m2×m3×…×mn种不同的方法。
维基百科


c3d6ab8969bc85ed4ccf3a64f420bb9a670d53ef

问题描述
冒泡排序是一种简单的排序算法。该算法反复扫描欲排序的列表,比较相邻元素对,若两者顺序不对,就将它们交换。这样对列表的扫描反复进行直至列表中不存在需要交换的元素为止,这意味着列表已经排好序。算法之所以叫此名字,是缘于最小的元素就像“泡泡”一样冒到列表的顶端,这是一种基于比较的排序算法。

冒泡排序是一种非常简单的排序算法,其运行时间为O(n2)。每趟操作从列表首开始,以此比较相邻项,需要时交换两者。重复进行若干趟这样的操作直至无需再做任何交换操作为止。假定恰好做了T趟操作,序列就按升序排列,我们就说T为对此序列的冒泡排序趟数。下面是一个例子。序列为“5 1 4 2 8”,对其施行的冒泡排序如下所示。

第一趟操作:

( 51 4 2 8 ) −> ( 1 5 4 2 8 ),比较头两个元素,并将其交换。

( 1 5 4 2 8 ) −> ( 1 4 5 2 8 ),交换,因为5 > 4。

( 1 4 5 2 8 ) −> ( 1 4 2 5 8 ),交换,因为5 > 2。

( 1 4 2 5 8 ) −> ( 1 4 2 5 8 )由于这两个元素已经保持顺序(8>5),算法不对它们进行交换。

第二趟操作:

( 1 4 2 5 8 ) −> ( 1 4 2 5 8 )

( 1 4 2 5 8 ) −> ( 1 2 4 5 8 ),交换,因为4 > 2。

( 1 2 4 5 8 ) −> ( 1 2 4 5 8 )

( 1 2 4 5 8 ) −> ( 1 2 4 5 8 )

在T = 2趟后,序列已经排好序,所以我们说对此序列冒泡排序的趟数为2。

ZX在算法课中学习冒泡排序,他的老师给他留了一个作业。老师给了ZX一个具有N个两两不等的元素的数组A,并且已经排成升序。老师告诉ZX,该数组是经过了K趟的冒泡排序得来的。问题是:A有多少种初始状态,使得对其进行冒泡排序,趟数恰为K?结果可能是一个很大的数值,你只需输出该数相对于模20100713的剩余。

输入

输入包含若干个测试案例。

第一行含有一个表示案例数的整数T (Tleqslant100 000)。

跟着的是T行表示各案例的数据。每行包含两个整数N和K(1leqslantNleqslant1,000,000, 0leqslantKleqslantN−1),其中N表示序列长度而K表示对序列进行冒泡排序的趟数。

输出

对每个案例,输出序列的初始情形数对模20100713的剩余,每个一行。

输入样例

3
3 0
3 1
3 2

输出样例

1
3
2

解题思路

(1)数据的输入与输出

根据输入文件格式的描述,首先在其中读出测试案例个数T。然后依次读取案例数据N和K。对每个案例计算进行K趟处理就能实现冒泡排序的数组A[1..N]有多少种可能的初始状态,并将所得结果作为一行写入输出文件。

1 打开输入文件inputdata
2 创建输出文件outputdata
3 从inputdata中读取案例数T
4 for t←1 to T
5   do 从inputdata中读取案例数据N, K
6      BUBLLE-SORT-ROUNDS(N, K, k, x, count)
7      将count作为一行写入outputdata中
8 关闭inputdata
9 关闭outpudata

其中,第6行调用过程BUBLLE-SORT-ROUNDS(N, K, k, x, count)计算进行K趟处理就能实现冒泡排序的数组A[1..N]有多少种可能的初始状态,是解决一个案例的关键。

(2)处理一个案例的算法过程

为方便计,我们假定序列A中的N个数为0,1,…,N-1。注意,冒泡排序的第k趟操作,总是将当前范围(A[0..k−1])内的最大的元素推至当前范围的最后位置A[k−1]。

除了针对趟数K=0的唯一初始状态A[0..N−1]已经有序外,我们归纳K=k(1leqslantk

K=1时,初始状态只能是1,…, N−1中的一个元素不出现在自己应有的位置上,而其他元素均处于相对顺序的位置上。对于1而言,它要出现在A[0]处;对于2而言,它可以出现在A[0]、A[1]处之一;…一般地,对于i(0

K=2时,初始状态可以是1,…, N−1中的两个元素不出现在应有的位置上,而其他元素均处于相对顺序的位置上。对于0

一般地,K=k(1leqslantk

若将1~N-1中的K个数0

**BUBLLE-SORT-ROUNDS(N, K, k, x, count) ▷k表示递归层次
1 if kgeqslantK ▷得到一个积
2 then item←1
3 for i←1 to K
4 do item←(itemxi) MOD 20100713
5 count←(count+item) MOD 20100713
6 return
7 if k=0
8 then begin←N-1, end← K ▷顶层,x[0]的取值范围
9 else begin←xk-1-1, end← K-k ▷k>1时,x[k]的取值范围
10 for p←begin downto end ▷确定第k个因子
11 do xk ← p
12 BUBLLE-SORT-ROUNDS(N, K, k+1)**
算法1-10 计算具有N个不同元素恰做K趟操作完成排序的序列初始状态数的过程

对测试案例数据N和K,上述过程运行如下。这是一个递归过程。递归层次由参数k表示,表示计算一个积中第k个因子。最顶层的调用应该是BUBLLE-SORT-ROUNDS(N, K, 0, x, count),即k=0。

第1~7行当检测到k>K时,意味着得到一个积的所有因子。由于20100713是一个素数,以它为模的剩余类[3]对加法和乘法运算是封闭的,所以,可以对每一步乘法运算求关于模20100713的剩余,也可以在将积累加到count时进行求关于模20100713的剩余。

第7~8行if-then-else结构针对k是否为1决定第k个因子的取值范围begin~end。

第9~12行的for循环完成对第k个因子xk的确定后,调用自身确定xk+1。

由于sum{_{1<{{i}_{1}}

解决本问题的算法的C++实现代码存储于文件夹laboratory/Bubble Sort中,读者可打开文件BubbleSort.cpp研读,并试运行之。

相关文章
机器学习/深度学习 算法 自动驾驶
142 0
|
1月前
|
机器学习/深度学习 算法 搜索推荐
从零开始构建图注意力网络:GAT算法原理与数值实现详解
本文详细解析了图注意力网络(GAT)的算法原理和实现过程。GAT通过引入注意力机制解决了图卷积网络(GCN)中所有邻居节点贡献相等的局限性,让模型能够自动学习不同邻居的重要性权重。
126 0
从零开始构建图注意力网络:GAT算法原理与数值实现详解
|
2月前
|
机器学习/深度学习 算法 文件存储
神经架构搜索NAS详解:三种核心算法原理与Python实战代码
神经架构搜索(NAS)正被广泛应用于大模型及语言/视觉模型设计,如LangVision-LoRA-NAS、Jet-Nemotron等。本文回顾NAS核心技术,解析其自动化设计原理,探讨强化学习、进化算法与梯度方法的应用与差异,揭示NAS在大模型时代的潜力与挑战。
306 6
神经架构搜索NAS详解:三种核心算法原理与Python实战代码
|
2月前
|
传感器 算法 定位技术
KF,EKF,IEKF 算法的基本原理并构建推导出四轮前驱自主移动机器人的运动学模型和观测模型(Matlab代码实现)
KF,EKF,IEKF 算法的基本原理并构建推导出四轮前驱自主移动机器人的运动学模型和观测模型(Matlab代码实现)
|
2月前
|
算法
离散粒子群算法(DPSO)的原理与MATLAB实现
离散粒子群算法(DPSO)的原理与MATLAB实现
90 0
|
3月前
|
机器学习/深度学习 人工智能 编解码
AI视觉新突破:多角度理解3D世界的算法原理全解析
多视角条件扩散算法通过多张图片输入生成高质量3D模型,克服了单图建模背面细节缺失的问题。该技术模拟人类多角度观察方式,结合跨视图注意力机制与一致性损失优化,大幅提升几何精度与纹理保真度,成为AI 3D生成的重要突破。
207 0
|
3月前
|
算法 区块链 数据安全/隐私保护
加密算法:深度解析Ed25519原理
在 Solana 开发过程中,我一直对 Ed25519 加密算法 如何生成公钥、签名以及验证签名的机制感到困惑。为了弄清这一点,我查阅了大量相关资料,终于对其流程有了更清晰的理解。在此记录实现过程,方便日后查阅。
179 1
|
4月前
|
消息中间件 存储 缓存
zk基础—1.一致性原理和算法
本文详细介绍了分布式系统的特点、理论及一致性算法。首先分析了分布式系统的五大特点:分布性、对等性、并发性、缺乏全局时钟和故障随时发生。接着探讨了分布式系统理论,包括CAP理论(一致性、可用性、分区容错性)和BASE理论(基本可用、软状态、最终一致性)。文中还深入讲解了两阶段提交(2PC)与三阶段提交(3PC)协议,以及Paxos算法的推导过程和核心思想,强调了其在ZooKeeper中的应用。最后简述了ZAB算法,指出其通过改编的两阶段提交协议确保节点间数据一致性,并在Leader故障时快速恢复服务。这些内容为理解分布式系统的设计与实现提供了全面的基础。
|
4月前
|
存储 算法 安全
Java中的对称加密算法的原理与实现
本文详细解析了Java中三种常用对称加密算法(AES、DES、3DES)的实现原理及应用。对称加密使用相同密钥进行加解密,适合数据安全传输与存储。AES作为现代标准,支持128/192/256位密钥,安全性高;DES采用56位密钥,现已不够安全;3DES通过三重加密增强安全性,但性能较低。文章提供了各算法的具体Java代码示例,便于快速上手实现加密解密操作,帮助用户根据需求选择合适的加密方案保护数据安全。
347 58

热门文章

最新文章