实验一:大整数乘法

article/2025/9/14 5:06:56

1.实验目的

  1. 掌握分治算法的基本思想、技巧和效率分析方法。
  2. 熟练掌握用递归设计分治算法的基本步骤。
  3. 学会利用分治算法解决实际问题。

2.实验内容

大整数乘法
采用分治算法实现两个n位二进制(或者十进制)大整数的乘法。

3.实验要求

  1. 根据实验内容构思设计算法,选取适合的数据结构;
  2. 对所设计的算法采用大O符号进行时间复杂性分析;
  3. 上机实现算法;
  4. 实验报告内容应包括问题描述、问题分析、算法设计、算法实现、运行结果及算法复杂度分析等内容。

4.算法设计

举个例子理解分治过程:
在这里插入图片描述

算法设计:
分解:

首先将2个大整数a(n位)、b(m位)分解为两部分:ah和al、bh和bl

ah表示大整数a的高位,al表示大整数a的低位, a = a h ∗ 1 0 n 2 + a l a=ah*10^{\frac{n}{2}}+al a=ah102n+al,ah、al为n/2位。

bh表示大整数b的高位,bl表示大整数b的低位, b = b h ∗ 1 0 m 2 + b l b=bh*10^{\frac{m}{2}}+bl b=bh102m+bl,bh、bl为m/2位。

2个大整数a(n位)、b(m位)相乘转换成了4个乘法运算 a h ∗ b h ah*bh ahbh a h ∗ b l ah*bl ahbl a l ∗ b h al*bh albh a l ∗ b l al*bl albl,而乘数的位数变为了原来的一半。

求解子问题:

继续分解两个乘法运算,直到分解有一个乘数位1位数时停止分解,进行乘法运算并记录结果。

合并:

将计算出的结果相加并回溯,求出最终结果。

5.算法步骤

#include<stdlib.h>
#include<cstring>
#include <iostream>using namespace std;
#define M 100
char sa[1000];
char sb[1000];
typedef struct _Node {int s[M];int l;int c;
} Node, *pNode;void cp(pNode src, pNode des, int st, int l) {int i, j;for (i = st, j = 0; i < st + l; i++, j++) {des->s[j] = src->s[i];}des->l = l;des->c = st + src->c;
}void add(pNode pa, pNode pb, pNode ans) {int i, cc, k, palen, pblen, len;int ta, tb;pNode temp;//保证pa是高次幂if ((pa->c < pb->c)) {temp = pa;pa = pb;pb = temp;}ans->c = pb->c;  //结果的幂取最少的幂cc = 0;palen = pa->l + pa->c; //pa的长度pblen = pb->l + pb->c; //pb的长度//选取最长的长度if (palen > pblen)len = palen;elselen = pblen;k = pa->c - pb->c; //k是幂差,len是最长的位数for (i = 0; i < len - ans->c; i++) {if (i < k)ta = 0;elseta = pa->s[i - k];if (i < pb->l)tb = pb->s[i];elsetb = 0;if (i >= pa->l + k)ta = 0;ans->s[i] = (ta + tb + cc) % 10;cc = (ta + tb + cc) / 10;}if (cc)ans->s[i++] = cc;ans->l = i;
}void mul(pNode pa, pNode pb, pNode ans) {int i, cc, w;int ma = pa->l >> 1, mb = pb->l >> 1;Node ah, al, bh, bl;Node t1, t2, t3, t4, z;pNode temp;if (!ma || !mb) {//如果pa是一位数,则和pb交换if (!ma) {temp = pa;pa = pb;pb = temp;}ans->c = pa->c + pb->c;w = pb->s[0]; //pb必为一位数cc = 0;for (i = 0; i < pa->l; i++) {//pa必为2位数以上ans->s[i] = (w * pa->s[i] + cc) % 10;cc = (w * pa->s[i] + cc) / 10;}if (cc)ans->s[i++] = cc;ans->l = i;return;}cp(pa, &ah, ma, pa->l - ma); //高位升幂cp(pa, &al, 0, ma);           //低位幂不变cp(pb, &bh, mb, pb->l - mb);cp(pb, &bl, 0, mb);mul(&ah, &bh, &t1); mul(&ah, &bl, &t2);mul(&al, &bh, &t3);mul(&al, &bl, &t4);add(&t3, &t4, ans);add(&t2, ans, &z);add(&t1, &z, ans);
}int main() {Node ans, a, b;cout << "输入大整数 a:" << endl;cin >> sa;cout << "输入大整数 b:" << endl;cin >> sb;a.l = strlen(sa);b.l = strlen(sb);int z = 0, i;for (i = a.l - 1; i >= 0; i--)a.s[z++] = sa[i] - '0';a.c = 0;z = 0;for (i = b.l - 1; i >= 0; i--)b.s[z++] = sb[i] - '0';b.c = 0;mul(&a, &b, &ans);cout << "最终结果为:";for (i = ans.l - 1; i >= 0; i--)cout << ans.s[i];cout << endl;return 0;
}

代码解释:

1、将两个输入的大数,倒序存储在数组s[]中,l表示长度,c表示幂,c初始为0。

2、cp函数:将一个n位的数,分成两个n/2的数并存储,记录它的长度和次幂。

3、mul函数,不断地分解,直到有一个乘数为1位数时停止分解,进行乘法并记录结果。

4、add函数,将分解得到的数,进行相加合并。

代码流程:
初始化:将a、b倒序存储在数组a.s[],b.s[]中。
在这里插入图片描述
分解:cp函数:将一个n位的数,分成两个n/2的数并存储,记录它的长度和次幂。ah表示高位,al表示低位,l用来表示数的长度,c表示次幂。

在这里插入图片描述
转换为4次乘法运算:ahbh,ahbl,albh,albl:
在这里插入图片描述
求解子问题:

ah ∗ * bh,ah ∗ * bl,al ∗ * bh,al ∗ * bl
在这里插入图片描述
继续求解子问题:

上述4个乘法运算都有一个乘数为1位数,可以直接进行乘法运算。以 a h h ∗ b h h ahh*bhh ahhbhh为例:

在这里插入图片描述
3首先和1相乘得到3存储在下面数组的第0位,然后3和4相乘得到12,先存储12%10=2,然后存储进位12/10=1,那样结果就为倒序的321,结果的次幂是两个乘数次幂之和。

4个乘法运算结果如下图:
在这里插入图片描述
合并:

合并子问题结果,返回给 a h ∗ b h ah*bh ahbh,将上面4个乘法运算的结果加起来返回给 a h ∗ b h ah*bh ahbh

在这里插入图片描述

由此得到ah*bh=13408x10^4。

用同样的方法求得 a h ∗ b l = 832 x 1 0 2 ah*bl=832x10^2 ahbl=832x102 a l ∗ b h = 32682 x 1 0 2 al*bh=32682x10^2 albh=32682x102,al ∗ * bl=2028。将这4个子问题结果加起来,合并得到原问题a*b=137433428。

6.实验分析

算法复杂度分析:
假设两个n位大整数相乘的时间复杂度为T(n),则:
在这里插入图片描述
当n>1时,可以递推求解如下:
在这里插入图片描述
递推最终的规模为1,令n=2^x,则x=logn,那么有:
在这里插入图片描述
大整数乘法的时间复杂度为O(n^2)。

空间复杂度:

程序中变量占用了一些辅助空间,都是常数阶,但合并时结点数组占用的辅助空间为O(n),递归调用所使用的栈空间时O(logn)。所以,空间复杂度为O(n)。

7.实验总结

通过这次实验,我进一步理解了用分治法求解大整数乘法的算法。大整数乘法是一个十分实用的问题,它通过减少两数相乘的次数,来达到降低间复杂度,提高算法效率的目的。


http://chatgpt.dhexx.cn/article/e7doCfSN.shtml

相关文章

分治法的经典问题——大整数相乘

分治法的原理 讨论问题时&#xff0c;先来了解一下什么是分治法。 分治法的意思就是&#xff0c;分而治之&#xff0c;也就是把一个问题&#xff0c;拆分成几个小问题&#xff0c;最后再汇总解决的方法 通过大整数相乘问题来了解分治法 假如现在我们要求两个大整数相乘的乘积…

大整数乘法(分治法)

大整数乘法&#xff08;分治法&#xff09; 题目描述&#xff1a;设X和Y都是n位的十进制整数&#xff0c;计算它们的乘积X*Y。 如果按照我们日常的计算方法&#xff0c;应该就是将两个数逐位相乘&#xff0c;最后加起来得到最终的结果&#xff0c;时间复杂度为O&#xff08;n2&…

大整数相乘算法

一 转换为二进制求&#xff0c;推导出的公式适合十进制计算 设X和Y都是n位的二进制整数&#xff0c;现在要计算它们的乘积XY。我们可以用小学所学的方法来设计一个计算乘积XY的算法&#xff0c;但是这样做计算步骤太多&#xff0c;显得效率较低。如果将每2个1位数的乘法或加法看…

【大整数乘法】

问题 2.伪代码 理想情况下&#xff0c;XY位数相同 Mul(long long x,long long y,int num){Fh<--(x*y>0)?1:-1;x<--|x|; y<--|y|;if(num 0)then return 0;else if(num1) then return fh*x*y;else{x_high<--x/10^(num/2);x_low<--x mod 10^(num/2);y_high…

大整数乘法(大整数乘int型)

算法思想&#xff1a; 1.将大整数倒序储存到数组中&#xff08;方便进位&#xff09; 2.对同位相乘后的数取模10&#xff0c;推入结果数组中 3.对同位相乘后的数除以10&#xff0c;作为进位 5.去除可能出现的前导零 4.完成乘法后倒序输出 补充知识&#xff1a; 1、vector相关用…

C语言实现大整数乘法

转载自&#xff1a;点击打开链接 乘法规律&#xff0c;一个数的第i位和另一个数的第j位相乘&#xff0c;一定会累加到结果的第ij位&#xff0c;结果的数组一个数组元素存2位数&#xff0c;最后对结果处理进位&#xff0c;最后打印出来 方法一见上面链接https://www.cnblogs.c…

大整数乘法(简单模拟乘法过程)

一、分析 整数的数值超过计算机硬件所能表示的最大值时&#xff0c;那么我们只能借助软件的方法来实现大整数的乘法了。 我们可以使用字符串来模拟大整数的乘法&#xff0c;算法的思想就是使用我们在小学时学过的乘法&#xff0c;一位位相乘&#xff0c;最后计算出结果。如下&…

算法总结——大整数乘法

问题描述 求两个不超过200位的非负整数的积。 输入数据 有两行&#xff0c;每行是一个不超过200位的非负整数&#xff0c;没有多余的前导0。 输出要求 一行&#xff0c;即相乘后的结果。结果里不能有多余的前导0&#xff0c;即如果结果是342&#xff0c;那么就不能输出为0342。…

大整数的乘法(分治法)

通常执行一次加法或乘法运算所需的计算时间看作一个仅取决于计算机硬件处理速度的常数。这个仅在参加运算的整数能在计算机硬件对整数的表示范围内直接处理才是合理的。若要精确地表示大整数并在计算结果中要求精确得到所有位数上的数字&#xff0c;就必须用软件的方法来实现大…

分治法-大整数乘法

问题分析&#xff1a; 在计算机上处理一些大数据相乘时&#xff0c;由于计算机硬件的限制&#xff0c;不能直接进行相乘得到想要的结果。可以将一个大的整数乘法分而治之&#xff0c;将大问题变成小问题&#xff0c;变成简单的小数乘法再进行合并&#xff0c;从而解决上述问题…

大整数乘法

设计一个有效的算法&#xff0c;可以计算两个n位大整数的乘法运算。 如果按照我们日常的计算方法&#xff0c;应该就是将两个数逐位相乘&#xff0c;最后加起来得到最终的结果。由于是大整数乘法&#xff0c;那么我们用string来存储这两个数&#xff0c;因为是要做乘法&#x…

大整数乘法算法

一 转换为二进制求&#xff0c;推导出的公式适合十进制计算 设X和Y都是n位的二进制整数&#xff0c;现在要计算它们的乘积XY。我们可以用小学所学的方法来设计一个计算乘积XY的算法&#xff0c;但是这样做计算步骤太多&#xff0c;显得效率较低。如果将每2个1位数的乘法或加法看…

大整数乘法的详解

一.问题 由于编程语言提供的基本数值数据类型表示的数值范围有限&#xff0c;不能满足较大规模的高精度数值计算&#xff0c;因此需要利用其他方法实现高精度数值的计算&#xff0c;于是产生了大数运算。尤其是乘法运算&#xff0c;下面就是大整数的乘法的过程&#xff08;加 …

Ubuntu server树莓派版本默认用户名密码及密码修改

树莓派安装的Ubuntu server镜像&#xff0c; 默认的初始用户及密码&#xff1a; ubuntu # user ubuntu # passwd默认信息查看 在烧入镜像的内存卡中&#xff0c; 可以查看到默认的用户信息 默认密码修改 在登录界面 输入初始化的用户名和密码后&#xff0c; 会提示是第一…

2022.04.04树莓派最新镜像问题,树莓派如何设置初始化的账户和密码

树莓派最新的arm64位系统&#xff0c;更新时间是2022年4月4日&#xff0c;这个版本的树莓派取消了默认的账户密码&#xff0c;也就是原来一直使用的pi和对应的默认密码raspberry被取消了&#xff0c;现在如果想要使用的话必须自己设置&#xff0c;下面有两种方法可以设置自己的…

树莓派启用无密码 sudo

启用无密码 sudo&#xff0c;可以在不提供密码的情况下在树莓派上运行程序。 登录 Raspberry Pi 命令行界面。假设 Raspberry Pi 的默认用户名和密码分别为 pi 和 raspberry。在命令行界面中&#xff0c;键入以下命令&#xff1a; sudo nano /etc/sudoers 3. 通过添加以下行启…

最新树莓派系统PUTTY用默认用户名和密码登录不上的解决方法

最近我在树莓派配置深度学习环境&#xff0c;然后直接载了别的博主的树莓派镜像&#xff0c;发现博主给的用户名&#xff0c;密码登不上&#xff0c;于是乎&#xff0c;就打算自己配置深度学习环境&#xff0c;结果我下在了最新版本的树莓派镜像系统&#xff08;2022-04-04-ras…

树莓派默认账号密码串口登录不了的Bug解决

一、问题总结 我用的树莓派型号是树莓派Pi3,刷机用的镜像是2023版的&#xff0c;23版的镜像文件较大8G的SD卡不够用 问题描述&#xff1a;刷完机在用串口登录树莓派的时候登录不了 &#xff01;&#xff01;&#xff01; 默认账号&#xff1a;pi 默认密码&#xff1a;raspb…

树莓派raspberry pi 4 SSH默认密码无法登录解决办法

以前玩过一段时间树莓派&#xff0c;只要开通ssh就可以&#xff0c;默认用户pi,默认密码: raspberry。 远程连接就可以。 但今天再玩却死活无法登录&#xff0c;如下&#xff1a; 出了什么幺蛾子哦&#xff1f;&#xff01;&#xff01; 上网一查&#xff0c;才知道pi账号在…

【入坑树莓派】烧录系统都烧录了三次(树莓派默认账户密码错误/已删除)

为什么会烧录了三次&#xff1f;我因为实在不知道问题出在哪&#xff0c;所以只能推倒重来三次。。。 三次&#xff0c;两次连接不上WiFi&#xff0c;好不容易一次连接上了&#xff0c;出现了下面这幅画面 再三确认了默认用户名是pi&#xff0c;密码raspberry&#xff0c;奈何…