经典算法题:大数乘法之乘法累加算法 Karatsuba算法(远远超出long long范围)

2023-11-19

问题:

超过100位数字的整数的乘法,无法直接调用*运算;

例如:

求 1234567891011121314151617181920 * 2019181716151413121110987654321 的乘积结果

需要转化成数组问题或者字符串问题求解,答案也用数组表示;

思路有两种:

  • 乘法累加法:

        输入数组num1 num2,注意要颠倒顺序 因为要从低位往高位处理(当然也可以不处理);

        第i位数字与第j位数字相乘的结果 应保存到arr(i+j)位;

        然后对arr数组进位c进行处理;

        输出答案字符串res(删除前导0)。

算法复杂度 O(n^2)

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
    string num1, num2;
    cin >> num1 >> num2;
    if(num1.size() == 0 || num2.size() == 0)
    {
        cout << 0 << endl;
        return 0;
    }
    reverse(num1.begin(),num1.end());
    reverse(num2.begin(),num2.end());
    vector<int> arr(num1.size() + num2.size());
    for(int i = 0; i < num1.size(); i++)
    {
        for(int j = 0; j < num2.size(); j++)
        {
            arr[i+j] += (num1[i] - '0') * (num2[j] - '0');
        }
    }
    string res;
    int c = 0;
    for(int i = 0; i < arr.size(); i++)
    {
        int num = arr[i] + c;
        c = num/10;
        res = char(num%10 + '0') + res;
    }
    if(c > 0)
        res = to_string(c)+res;
    int i = 0;
    while(i < res.size() && res[i] == '0')
        i++;
    cout << res.substr(i) << endl;
}
  • Karatsuba算法 分治法

       例如: A  |  B  *  C  |  D

        其中数字1(A|B)和数字2(C|D)的分段一致(n/2);

        处理如下:ans = AC * 10^{n} + (AD + BC) * 10^{n/2} + BD

       而AD + BC = (A + B) * (C + D) - AC - BD

        这样的话就可以利用前后得到的结果;

        大问题可以依次分解成为小问题,分治法的思路!

        算法复杂度:O(n^{log_2 3})

        注意:显示的数字顺序与实际相反,因此最后的结果需要反转!

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
//所有数字都是从低到高 比如string "123" 表示数字321
string add(string a, string b)
{
    int m = a.size(), n = b.size();
    if(m == 0) return b;
    if(n == 0) return a;
    int i = 0, j = 0, c = 0;
    string res;
    while(i < m && j < n)
    {
        int num = a[i] - '0' + b[j] - '0' + c;
        c = num/10;
        res += (char)(num%10 + '0');
        i++;
        j++;
    }
    while(i < m)
    {
        int num = a[i] - '0' + c;
        c = num/10;
        res += (char)(num%10 + '0');
        i++;
    }
    while(j < n)
    {
        int num = b[j] - '0' + c;
        c = num/10;
        res += (char)(num%10 + '0');
        j++;
    }
    if(c > 0)
        res += '1';
    return res;
}
//不考虑出现负数可能出现的情况
string sub(string a, string b)
{
    int m = a.size(), n = b.size();
    if(m == 0 || n == 0) return "0";
    int i = 0, j = 0, c = 0;
    string res;
    while(i < m && j < n)
    {
        int num = (a[i] - '0') - (b[j] - '0') - c;
        if(num < 0)
        {
            c = 1;
            num += 10;
        }
        else c = 0;
        res += (char)(num%10 + '0');
        i++;
        j++;
    }
    while(i < m)
    {
        int num = a[i] - '0' - c;
        if(num < 0)
        {
            c = 1;
            num += 10;
        }
        else c = 0;
        res += (char)(num%10 + '0');
        i++;
    }
    while(j < n)
    {
        int num = - b[j] + '0' - c;
        if(num < 0)
        {
            c = 1;
            num += 10;
        }
        else c = 0;
        res += (char)(num%10 + '0');
        j++;
    }
    //cout << "res = " << res << endl;
    int k = res.size() -1;
    while(k >= 0  && res[k] == '0')
        k--;
    return res.substr(0,k+1);
}
string mul(string a, string b)
{
    int m = a.size(), n = b.size();
    string res;
    if(m == 0 && n == 0) return "0";
    else if(m == 1 && n == 1)
    {
        int num = (a[0]-'0')*(b[0]-'0');
        res = to_string(num);
        reverse(res.begin(),res.end());
        return res;
    }
    int len = max(m,n);
    while(m < len)
    {
        a.push_back('0');
        m++;
    }
    while(n < len)
    {
        b.push_back('0');
        n++;
    }
    int mid = len/2;
    if(len%2 == 1)
        mid += 1;
    string A = a.substr(mid), B = a.substr(0,mid);
    string C = b.substr(mid), D = b.substr(0,mid);
    string AC = mul(A,C);
    cout << A << " * " << C << " = " << AC << endl;
    string BD = mul(B,D);
    cout << B << " * " << D << " = " << BD << endl;
    string M0 = add(A,B);//A+B
    cout << A << " + " << B << " = " << M0 << endl;
    string M1 = add(C,D);//C+D
    cout << C << " + " << D << " = " << M1 << endl;
    string M2 = mul(M0,M1);
    cout << M0 << " * " << M1 << " = " << M2 << endl;
    string M3 = sub(M2,AC);
    cout << M2 << " - " << AC << " = " << M3 << endl;
    M3 = sub(M3,BD);
    cout << "M3" << " - " << BD << " = " << M3 << endl;
    if(BD.size() > mid)
    {
        M3 = add(M3,BD.substr(mid));
        BD = BD.substr(0,mid);
    }
    if(M3.size() > mid)
    {
        AC = add(AC,M3.substr(mid));
        M3 = M3.substr(0,mid);
    }
    res = BD+M3+AC;
    return res;
}
int main()
{
    string num1, num2;
    cin >> num1 >> num2;
    if(num1.size() == 0 || num2.size() == 0)
    {
        cout << 0 << endl;
        return 0;
    }
    reverse(num1.begin(),num1.end());
    reverse(num2.begin(),num2.end());
    string res = mul(num1,num2);
    reverse(res.begin(),res.end());
    int i = 0;
    while(i < res.size() && res[i] == '0')
        i++;
    cout << res.substr(i) << endl;
}
  • 答案揭晓

1234567891011121314151617181920 * 2019181716151413121110987654321 =

2492816912877266687794240983772975935013386905490061131076320

请验证一下。 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

经典算法题:大数乘法之乘法累加算法 Karatsuba算法(远远超出long long范围) 的相关文章

  • 在java程序中使用c++ Dll

    我正在尝试使用System LoadLibrary 使用我用 C 编写的一个简单的 dll UseDllInJava java import com sun jna Library import com sun jna Native imp
  • clang 格式换行符在错误的位置

    给出以下代码行 get abc manager get platform status abc platform status sw update status fill update status actions allowed stat
  • 如何使用 zlib 制作 .zip 文件

    我正在阅读zlib的文档 它相当详细 但我读到了这一行 输出数据将位于zlib格式 与 gzip 或zip formats http www zlib net zlib how html http www zlib net zlib how
  • 分段错误(核心转储)错误

    我的程序编译罚款 但在输入文件时出现 分段错误 核心转储 错误 我没有正确处理 ostream 吗 include
  • 内联函数/方法

    声明 内联函数必须在调用之前定义 这个说法正确吗 EDIT 该问题最初是德语 内联功能穆森 弗 伊赫雷姆 奥夫鲁夫定义 sein 也许它对任何人都有帮助 是的 它是正确的 但只是部分正确 它可能正确地重新构建如下 内联函数必须在每个翻译单位
  • mprotect 之后 malloc 导致分段错误

    在使用 mprotect 保护内存区域后第一次调用 malloc 时 我遇到分段错误 这是执行内存分配和保护的代码片段 define PAGESIZE 4096 void paalloc int size Allocates and ali
  • 对 boost 库的依赖项没有完整路径

    我已经成功构建了动态库 依赖于使用自定义前缀构建和安装的 boost 库 b2 install prefix PREFIX 然而 当我跑步时otool L在我的库中 我得到如下输出 libboost regex dylib compatib
  • 将带有 glut 的点击坐标添加到向量链接列表中

    我想创建一个向量链接列表 并在 GLUT 库的帮助下获取点击的位置并将它们附加到链接列表中 这些是我写的结构 typedef struct vector int x int y Vector typedef struct VectorLis
  • 两种类型的回发事件

    1 我发现了两篇文章 每篇文章对两种类型的回发事件的分类都略有不同 一位资源说两种类型的回发事件是Changed事件 其中控件实现 IPostbackDataHandler 当数据在回发之间更改时触发 然后Raised事件 其中控件实现 I
  • OpenCV 2.4.3 中的阴影去除

    我正在使用 OpenCV 2 4 3 最新版本 使用内置的视频流检测前景GMG http docs opencv org modules gpu doc video html highlight gmg gpu 3a 3aGMG GPU算法
  • 使用 WF 的多线程应用程序的错误处理模式?

    我正在写一个又长又详细的问题 但只是放弃了它 转而选择一个更简单的问题 但我在这里找不到答案 应用程序简要说明 我有一个 WPF 应用程序 它生成多个线程 每个线程执行自己的 WF 处理线程和 WF 中的错误 允许用户从 GUI 端进行交互
  • C++ 错误 - “成员初始值设定项表达式列表被视为复合表达式”

    我收到一个我不熟悉的 C 编译器错误 可能是一个非常愚蠢的错误 但我不能完全指出它 Error test cpp 27 error member initializer expression list treated as compound
  • 从 R 到 C 处理列表并访问它

    我想使用从 R 获得的 C 列表 我意识到这个问题与此非常相似 使用 call 在 R 和 C 之间传递数据帧 https stackoverflow com questions 6658168 passing a data frame f
  • .NET 客户端中 Google 表格中的条件格式请求

    我知道如何在 Google Sheets API 中对值和其他格式进行批量电子表格更新请求 但条件格式似乎有所不同 我已正确设置请求 AddConditionalFormatRuleRequest formatRequest new Add
  • 为什么要在 C++ 中使用 typedef?

    可以说我有 set
  • ASP.NET JQuery AJAX POST 返回数据,但在 401 响应内

    我的应用程序中有一个网页 需要调用我设置的 Web 服务来返回对象列表 这个调用是这样设置的 document ready function var response ajax type POST contentType applicati
  • 使用 iTextSharp 5.3.3 和 USB 令牌签署 PDF

    我是 iTextSharp 和 StackOverFlow 的新手 我正在尝试使用外部 USB 令牌在 C 中签署 PDF 我尝试使用从互联网上挖掘的以下代码 Org BouncyCastle X509 X509CertificatePar
  • 在 C++17 中使用 成员的链接错误

    我在 Ubuntu 16 04 上使用 gcc 7 2 并且需要使用 C 17 中的新文件系统库 尽管确实有一个名为experimental filesystem的库 但我无法使用它的任何成员 例如 当我尝试编译此文件时 include
  • 为什么 Linux 对目录使用 getdents() 而不是 read()?

    我浏览 K R C 时注意到 为了读取目录中的条目 他们使用了 while read dp gt fd char dirbuf sizeof dirbuf sizeof dirbuf code Where dirbuf是系统特定的目录结构
  • 如何使用 C# 以低分辨率形式提供高分辨率图像

    尝试使用 300dpi tif 图像在网络上显示 目前 当用户上传图像时 我正在动态创建缩略图 如果创建的页面引用宽度为 500x500px 的高分辨率图像 我可以使用相同的功能即时转换为 gif jpg 吗 将创建的 jpg 的即将分辨率

随机推荐

  • WPF TextBlock 实现点击事件

    TextBlock 标签里定义MouseLeftButtonDown 事件 xaml cs
  • ICCV 2023

    ICCV 2023 MPI Flow 从单视角构建的多平面图像中学习光流 引言 主要贡献 Motivation 算法细节 Optical Flow Data Generation Independent Object Motions Dep
  • Node之使用dns模块解析域名

    引 在网络编程中 开发者更倾向于使用域名 而不是IP地址来指定网络连接的目标地址 在Node js中 提供dns模块 以实现域名查找及域名解析的处理 在dns模块中 提供了三个主方法及一系列便捷方法 其中三个主方法分别为用于将一个域名解析为
  • MySQL使用查询结果生成临时表

    MySQL中不支持对同一个表使用其查询结果更新or删除本表内数据 也就是update或delete后的where条件为针对相同表的select 解决方案是创建临时表做过度保存中间数据 可以直接使用查询结果来形成临时表 CREATE TABL
  • verilog奇数分频器的问题讲解(7分频为例)

    先不多哔哔 直接上代码 verilogHDL 代码的后面讲原理 module fenpin3 clk clk7 rst input clk rst 设置rst的目的是当rst 1的时候给cnt0和cnt1赋初值 output clk7 re
  • python sslerror_如何解决“不良握手”问题利用python请求时的SSLErrors

    I m trying to get access to the BambooHR API documentation here but I receive the following error params user username p
  • GREASELM: GRAPH REASONING ENHANCED LANGUAGE MODELS FOR QUESTION ANSWERING

    本文是LLM系列文章 针对 GREASELM GRAPH REASONING ENHANCED LANGUAGE MODELS FOR QUESTION ANSWERING 的翻译 GREASELM 图推理增强的问答语言模型 摘要 1 引言
  • 小霸王其乐无穷之函数回调

    小霸王游戏机是中国上一代备受欢迎的家用游戏机 它在1990年代初期开始流行 当时 由于游戏软件受限 国内的游戏市场相对匮乏 这使得小霸王游戏机成为许多70 80后童年时光中难忘的一部分 小霸王游戏机分为两大主要部分 游戏机本身和卡带 游戏机
  • Python中的CALL_FUNCTION指令

    在Python字节码中 CALL FUNCTION指令后跟的数字代表这次函数调用需要从栈上取出的参数的数量 具体来说 这个数字包括位置参数和关键字参数的数量 这个数字的低两位表示位置参数的数量 然后每两位表示一个关键字参数的数量 因此 如果
  • LLVM Language Reference Manual---阅读笔记

    文档地址 http llvm org docs LangRef html LLVM IR的标示符有两种基本类型 全局的和局部的 全局标示符以 开头 局部标示符以 开头 LLVM IR的标示符有三种形式 命名的 未命名的 常量 每一个Moud
  • Python pyecharts数据可视化

    Python pyecharts数据可视化 绘制精美图表 一 数据可视化 1 pyecharts介绍 2 初入了解 1 快速上手 2 简单的配置项介绍 3 案例实战 1 柱状图Bar 2 地图Map 省份 城市 地区 3 饼图Pie Pie
  • 【SMTP】【POP】电子邮件相关协议分析

    一 实验环境 通过普通路由器连接英特网的计算机一台 通过VMWare安装的Linux虚拟机一台 抓包工具 Wireshark 邮件处理软件 Foxmail 二 实验原理 SMTP工作原理 SMTP提供了一种邮件传输的机制 当收件方和发件方都
  • 公司实战 ElasticSearch+Kafka+Redis+MySQL

    一 需求 前一段时间公司要进行数据转移 将我们ES数据库中的数据转移到客户的服务器上 并且使用定时将新增的数据同步 在这过程中学到了很多 在此记录一下 二 技术栈 Mysql Redis ElasticSearch Kafka 三 方案 为
  • Ant Design Pro + Ant Design + React 踩坑记录

    1 自定义封装组件 1 1 组件通信 1 1 1 父传子 在本项目中对因为删除组件比较通用 所以对删除组件进行了封装 如下图我们对定义了通用删除组件 通过props传入回调方法 这样页面上只需要引用该组件 并传入自定义的删除函数即可引入 我
  • 单向链表实现(C语言)

    目录 一 简介 概念介绍 链接存储方法 结点结构 头指针head和终端结点 二 单向链表的使用 1 数据结构 2 从尾部添加append 3 从头部添加 add head 4 在链表任一指定位置节点按升序插入节点 5 查找并删除指定节点 6
  • [透彻]为什么要前后端分离?

    前后端分离的意义 前后端分离 已成为互联网项目开发的业界标准使用方式 前后端分离 会为以后的大型分布式架构 弹性计算架构 微服务架构打下坚实的基础 核心思想 前端页面调用后端的restuful api接口 并使用json数据进行交互 服务器
  • ug建模文本怎么竖着_【UG三维造型】:UG NX三维特征孔

    UG NX是集CAD CAM CAE功能于一体的软件集成系统 是当今较为流行的一种数控模具设计软件 主要是因为其功能强大 包括了世界上最强大 最广泛的产品设计应用模块 数控编程模块 模具设计模块 工程制图模块 装配设计模块 钣金设计模块 运
  • 第12课:生活中的构建模式——想要车还是庄园

    用程序来模拟生活 从剧情中思考构建模式 与工厂模式的区别 与组合模式的区别 构建模式的模型抽象 类图 基于升级版的实现 模型说明 应用场景 故事剧情 下周就要过年了 这是 Tony 工作后的第一个春节 还是在离家这么远的北京工作 所以肯定不
  • Ribbon负载均衡(三)SpringCloud Ribbon负载均衡详解及实现

    SpringCloud Ribbon负载均衡实现 文章目录 SpringCloud Ribbon负载均衡实现 1 User客户端调用方 1 1 修改User服务 Pom文件 引入Ribbon 1 2 RibbonConfiguration配
  • 经典算法题:大数乘法之乘法累加算法 Karatsuba算法(远远超出long long范围)

    问题 超过100位数字的整数的乘法 无法直接调用 运算 例如 求 1234567891011121314151617181920 2019181716151413121110987654321 的乘积结果 需要转化成数组问题或者字符串问题求