当前位置: 首页 > 编程日记 > 正文

朴素高精度乘法的常数优化

2015年辽宁省赛热身赛有一道高精度乘法

传送门:NEUOJ 1574 A*B

1574: A * B

时间限制: 10 Sec  内存限制: 128 MB

题目描述

Calculate $a \times b$.

输入

Your program will be tested on one or more test cases. In each test case, two integer $a$, $b$ ($0\le a,b\le 10^{100000}$).

 

输出

For each test case, print the following line:

answer

where answer is $a\times b$.

样例输入

1000000000000000 2000000000000000

样例输出

2000000000000000000000000000000

提示

来源

2015省赛热身赛

朴素高精度乘法的典型写法是

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int MAX_N=1e5+10;
 5 char sa[MAX_N], sb[MAX_N];
 6 int a[MAX_N], b[MAX_N], res[MAX_N<<1];
 7 int main(){
 8     //freopen("in", "r", stdin);
 9     while(~scanf("%s%s", sa, sb)){
10         int i, j;
11         memset(res, 0, sizeof(res));
12         for(i=0; sa[i]; i++){
13              for(j=0; sb[j]; j++){
14                  res[i+j]+=(sa[i]-'0')*(sb[j]-'0');
15              }
16         }
17         int tot=i+j-2;    //error-prone
18         for(i=tot; i; i--){
19             res[i-1]+=res[i]/10;
20             res[i]%=10;
21         }
22         printf("%d", res[0]);    //error-prone
23         if(res[0]) for(i=1; i<=tot; i++) printf("%d", res[i]);
24         puts("");
25     }
26     return 0;
27 }

但这样写会TLE。下面要介绍一种常数优化:

将大整数从低位到高位每 $6$ 位分成一组(最后一组若不够 $6$ 位自动在高位补 $0$),这样便自然得到了大整数的「一百万进制」表示将每组内的十进制计数看成是一百万进制的一个“数字”,由于小于一百万的数的乘法无需采用高精度计算,可认为是 $O(1)$ 的,实际上对于不致溢出的小整数,机器实现的乘法比模拟竖式计算要快好多。这样便在原来十进制表示下的朴素高精度乘法的基础上,实现了常数优化。这样的常数优化常常是有效的。

 1 #include<cstdio>
 2 #include<cstring>
 3 #define set0(a) memset(a, 0, sizeof(a))
 4 using namespace std;
 5 const int MAX_N=1e5+10;
 6 typedef long long ll;
 7 char sa[MAX_N], sb[MAX_N];
 8 ll a[MAX_N], b[MAX_N], res[MAX_N<<1];
 9 int base=6;
10 ll mod=1e6;
11 int trans(char *s, ll *a){  //value-passed
12     //memset(a, 0, sizeof(a));    //error-prone
13     int ls=strlen(s), len=(ls+base-1)/base;
14     int now=0, rem=ls%base;
15     int l, r;
16     if(rem){
17         l=0; r=rem;
18         for(int i=r-1, p=1; i>=l; i--, p*=10){
19             a[0]+=(s[i]-'0')*p;
20         }
21         now++;
22     }
23     for(int i=0; now<len; now++, i++){
24         l=rem+base*i, r=l+base; //error-prone
25         for(int j=r-1, p=1; j>=l; j--, p*=10){
26             a[now]+=(s[j]-'0')*p;
27         }
28     }
29     return len;
30 }
31  
32 int main(){
33     //freopen("in", "r", stdin);
34     while(~scanf("%s%s", sa, sb)){
35         set0(a); set0(b); set0(res);
36         int la=trans(sa, a), lb=trans(sb, b);
37         for(int i=0; i<la; i++){
38             for(int j=0; j<lb; j++){
39                 res[i+j]+=a[i]*b[j];
40             }
41         }
42         int tot=la+lb-2;
43         for(int i=tot; i; i--){
44             res[i-1]+=res[i]/mod;
45             res[i]%=mod;
46         }
47         int i;
48         for(i=0; i<=tot&&!res[i]; i++);
49         if(i>tot) putchar('0');
50         else{
51             printf("%lld", res[i++]);   //error-prone
52             for(; i<=tot; i++) printf("%06lld", res[i]);
53         }
54         puts("");
55     }
56     return 0;
57 }

Time: 4158MS

选择每 $6$ 个分一组是要保证运算过程不会溢出 long long,就本题的数据范围而言,取 $7$ 位分为一组也可,这样常数会更优,只需将上面的代码稍加修改(注意加粗的三行)

 1 #include<cstdio>
 2 #include<cstring>
 3 #define set0(a) memset(a, 0, sizeof(a))
 4 using namespace std;
 5 const int MAX_N=1e5+10;
 6 typedef long long ll;
 7 char sa[MAX_N], sb[MAX_N];
 8 ll a[MAX_N], b[MAX_N], res[MAX_N<<1];
 9 int base=7;
10 ll mod=1e7;
11 int trans(char *s, ll *a){  //value-passed
12     //memset(a, 0, sizeof(a));    //error-prone
13     int ls=strlen(s), len=(ls+base-1)/base;
14     int now=0, rem=ls%base;
15     int l, r;
16     if(rem){
17         l=0; r=rem;
18         for(int i=r-1, p=1; i>=l; i--, p*=10){
19             a[0]+=(s[i]-'0')*p;
20         }
21         now++;
22     }
23     for(int i=0; now<len; now++, i++){
24         l=rem+base*i, r=l+base; //error-prone
25         for(int j=r-1, p=1; j>=l; j--, p*=10){
26             a[now]+=(s[j]-'0')*p;
27         }
28     }
29     return len;
30 }
31  
32 int main(){
33     //freopen("in", "r", stdin);
34     while(~scanf("%s%s", sa, sb)){
35         set0(a); set0(b); set0(res);
36         int la=trans(sa, a), lb=trans(sb, b);
37         for(int i=0; i<la; i++){
38             for(int j=0; j<lb; j++){
39                 res[i+j]+=a[i]*b[j];
40             }
41         }
42         int tot=la+lb-2;
43         for(int i=tot; i; i--){
44             res[i-1]+=res[i]/mod;
45             res[i]%=mod;
46         }
47         int i;
48         for(i=0; i<=tot&&!res[i]; i++);
49         if(i>tot) putchar('0');
50         else{
51             printf("%lld", res[i++]);   //error-prone
52             for(; i<=tot; i++) printf("%07lld", res[i]);
53         }
54         puts("");
55     }
56     return 0;
57 }

 Time: 2937MS(这结果在所有AC的提交中算是很优的了)

当然高精度乘法有复杂度更优的解法,比如快速傅立叶变换(FFT),但通过本题,我们看到这种代码量较小的分组常数优化对于 $N$ 不太大,时限较宽的问题还是很有效的。

转载于:https://www.cnblogs.com/Patt/p/4625353.html

相关文章:

计算机专业今后的发展方向

计算机专业毕业后&#xff0c;大致的工作方向是软、硬、网、图 四大类&#xff0c;尤其以软件、网络为现今的首选 。从岗位上分&#xff0c;又可以分为技术道路、营销道路两大方向。 if 你选择硬件技术&#xff0c;then 从现在开始&#xff0c;牢记&#xff1a;天道酬勤&#x…

新警达尼亚尔·迪力木拉提的春运一天

新春佳节临近&#xff0c;乌鲁木齐铁路公安处民警坚守一线&#xff0c;保障旅客安全乘车。达尼亚尔迪力木拉提&#xff0c;今年26岁&#xff0c;新疆伊犁州伊宁市人&#xff0c;毕业于大连理工大学。2017年通过国家公务员考试入警为乌鲁木齐铁路公安局乌鲁木齐公安处见习民警&a…

9 单元测试中不得不知的概念

单元测试中不得不知的概念 前言软件单元及单元测试驱动函数和桩函数总结前言 做单元测试,如果不弄清楚什么是单元,那十八般武器也无的放矢了。可能在单元测试中听到最多的就是驱动函数、桩函数和逻辑覆盖,本专题就讲讲关于单元测试中那些不得不知的概念。关于逻辑覆盖,涉及…

php JSON数据格式化输出方法

php 的json_encode能把数组转换为json格式的字符串。字符串没有缩进&#xff0c;中文会转为unicode编码&#xff0c;例如\u975a\u4ed4。人阅读比较困难。现在这个方法在json_encode的基础上再进行一次美化处理。使人能方便阅读内容。 1. 使用 json_encode 输出 1 <?php2 3 …

转:C#中的abstract与virtual

C#中的abstract与virtual2008-03-14 14:01【abstract】 abstract 修饰符可以和类、方法、属性、索引器及事件一起使用。在类声明中使用 abstract 修饰符以指示类只能是其他类的基类。 抽象类具有以下特性&#xff1a; 抽象类不能实例化。 抽象类可以包含抽象方法和抽象访问器。…

从零开始单排学设计模式「UML类图」定级赛

阅读本文大概需要 3.5 分钟。本篇是设计模式系列的开篇&#xff0c;虽然之前也写过相应的文章&#xff0c;但是因为种种原因后来断掉了&#xff0c;而且发现之前写的内容也很渣&#xff0c;不够系统。所以现在打算重写&#xff0c;加上距离现在也有一段时间了&#xff0c;也算是…

10 单元测试使命

单元测试的使命前言单元测试要完成的内容总结前言 不同级别的测试的侧重点是不同的&#xff0c;单元测试也有它的使命所在。 单元测试要完成的内容 单元测试的重点主要包括验证功能的正确性、检查局部数据结构正确性、检查临界数据处理正确性、检查模块接口正确性和验证单元容…

MVVM test

示例代码 public class RegisterUserViewModel{public UserInfo userInfo { get; set; }public ICommand ClickCommand { get; set; }public RegisterUserViewModel(){userInfo new UserInfo();userInfo.Age 25;this.ClickCommand new DelegateCommand<object>(OnClic…

[SCOI2009]生日礼物

这道题很容易看出是一道单调队列题。 首先我们根据珠子的位置排序。 然后按顺序枚举一个个珠子。 如果该种珠子没有出现过标记上它的位置&#xff0c;如果出现过修改并打上当前位置。当所有珠子都出现后&#xff0c;将当前位置减去打标记位置最小的一个即为当前解。 可以证明正…

.Net(c#) 通过 Fortran 动态链接库,实现混合编程

c# 与 Fortran 混合编程解决方案主要有两种&#xff1a;1. 进程级的交互&#xff1a;在 Fortran 中编译为控制台程序&#xff0c;.Net 调用&#xff08;System.Diagnostics.Process&#xff09;&#xff0c;然后使用 Process 的 StandardOutput 属性读取控制台输出内容&#xf…

11关于集成测试

集成测试的必要性 前言集成测试集成测试模式和方法总结前言 差之毫厘,失之千里。 集成测试 单元测试的目的是确认软件单元能够满足所规定的要求,将一些单元按一定的要求合成在一起就组成了集合体。集成测试的目的是确认集合体能够正确地满足所规定的要求,集成后的各软件单…

Maven 手动添加第三方依赖包及编译打包和java命令行编译JAVA文件并使用jar命令打包...

一&#xff0c;实例:新建了一个Maven项目,在eclipse中通过 build path –> configure path….将依赖包添加到工程中后&#xff0c;eclipse不报错了。但是用Maven命令 mvn clean compile 时出错如下&#xff1a; 原因是在eclipse中添加了 exteneral jar后&#xff0c;还需要在…

Codeforces Educational round 58

Ediv2 58 随手AK.jpgD 裸的虚树&#xff0c;在这里就不写了 E 傻逼贪心&#xff1f;这个题过的比$B$都多.jpg #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <cstdlib> #include <queue> #includ…

VC 单文档程序 隐藏程序及任务栏图标

1 在APP类InitInstance()里 注释掉&#xff1a; m_pMainWnd->ShowWindow(SW_SHOW); 2 CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)里加 AfxGetApp()->m_nCmdShow SW_HIDE; 3 隐藏任务栏图标&#xff1a; ModifyStyleEx(WS_EX_APPWINDOW,WS_EX_TOOLWINDOW…

12 集成测试方法之大棒集成方法

大棒集成方法大棒集成方法总结大棒集成方法 大棒集成方法先是对每一个子模块进行测试&#xff08;单元测试阶段&#xff09;&#xff0c;然后将所有模块一次性的全部集成起来进行集成测试。如图&#xff0c;先分别对A、B、C、D、E、F、G模块进行单元测试&#xff0c;然后按照设…

phonegap+emberjs+python手机店发展,html5实现本地车类别~

商城开发项目&#xff0c;现在需要做出APP&#xff0c;无奈出场前android但不是很精通。最后选择phonegap实现app。 由于之前办理购物车分为登陆和登陆后两种情况&#xff0c;登录前必须充分利用本地存储。而基于phonegap本地存储的发展是使用Html5的localstorage功能实现。特分…

世上最伟大的十个公式,1+1=2排名第七,质能方程排名第五

英国科学期刊《物理世界》曾让读者投票评选了“最伟大的公式”&#xff0c;最终榜上有名的十个公式既有无人不知的112&#xff0c;又有著名的Emc2&#xff1b;既有简单的-圆周公式&#xff0c;又有复杂的欧拉公式…… 从什么时候起我们开始厌恶数学&#xff1f;这些东西原本如此…

20位程序员关于求职的疑问,以及我给出的参考答案

作者&#xff1a;陆小凤首发&#xff1a;公众号【程序员江湖】阅读本文大概需要 6 分钟。前几天发了一条朋友圈对于求职小伙伴们提出的问题&#xff0c;我进行了收集整理&#xff0c;统一反馈。也许这20个问题也是你们遇到的问题&#xff0c;所以趁着年前赶紧把它发出来。以下2…

14 集成测试方法之自底向上集成方法

自底向上集成方法前言自底向上集成方法前言 集成测试方法没有好坏之分&#xff0c;只有哪个更适合。 自底向上集成方法 自底向上集成方法是从调用的底层开始逐级的向上集成&#xff0c;每测试完一个族群就将其挂到上一层的模块上。这种集成方法的特点是不需要写桩函数&#x…

JavaScript Document

document:文档对象 document.getElementById();//根据ID获取元素对象 document.getElementsByTagName();//根据标签名获取元素对象数组 document.getElementsByClassName();//根据类名获取元素对象数组 document.getElementsByName();//根据名字获取元素对象数组 document.crea…

effective C++ 读书笔记(11-28)

1: RAII 资源获得时机便是初始化时机 典型应用&#xff1a; 智能指针&#xff01; 2&#xff1a; 为什么 auto_ptr 指针复制之后 原指针就会变成NULL &#xff1a; 多分指针指向它 会被析构多次 delete 函数会多次调用 3&#xff1a; 我要再次留心 stl容器的数据结构 与 特性…

15 三明治集成方法和混合策略集成方法

三明治集成方法和混合策略集成方法 前言三明治集成方法混合策略集成方法总结前言 关于集成测试方法今天我们再学习两个方法,三明治集成方法和混合策略集成方法。 三明治集成方法 采用三明治方法的优点是:它将自顶向下和自底向上的集成方法有机地结合起来,不需要写桩函数,…

产品经理和程序员的爱恨情仇

产品经理跪求程序员&#xff0c;程序员跪求程序成功上线&#xff01;前几天纯银V在微博上发了一条微博「很多人吐槽“人人都是产品经理”这句话&#xff0c;其实在我看来&#xff0c;这句话的正确理解是“人人都应该学习产品经理的思维方式&#xff0c;来提升自己的专业能力”&…

DES加密算法安全性评估

DES加密算法应用误区 DES算法具有极高安全性&#xff0c;到目前为止&#xff0c;除了用穷举搜索法对DES算法进行攻击外&#xff0c;还没有发现更有效的办法。而56位长的密钥的穷举空间为256&#xff0c;这意味着如果一台计算机的速度是每一秒种检测一百万个密钥&#xff0c;则它…

css3伪元素选择器before 和 after 的使用

:before 的作用, 在子元素的最前面, 添加一个伪元素, 伪元素内容通过 content 控制,可以在content属性中写入文本内容&#xff0c;但是通常为空字符串。 :after 的作用, 在子元素的最后面, 添加一个伪元素, 伪元素内容通过 content 控制,可以在content属性中写入文本内容&#…

16 系统测试之功能测试

功能测试前言功能测试总结前言 系统测试一般要使系统软件运行于真实的硬件环境中&#xff0c;其更倾向于软硬件结合的测试。在本专题中主要介绍系统测试中的功能测试和性能测试。其他测试类型在本专题中咱不展开讲&#xff0c;会在以后的专题中详细说。 功能测试 对于功能测试…

TinyMCE的使用-安装

TinyMCE安装非常简单&#xff0c;它可以被初始化为<form>标签中的<textarea>&#xff0c;当提交表单时&#xff0c;TinyMCE编辑器的内容将作为<form>表单的一部分被提交。 步骤1&#xff1a;下载TinyMCE并将其放在网站服务器目录 下载TinyMCE将得到的zip包加…

查看存储过程死锁的存储过程

create proc p_lockinfokill_lock_spid bit1, --是否杀掉死锁的进程,1 杀掉, 0 仅显示show_spid_if_nolock bit1 --如果没有死锁的进程,是否显示正常进程信息,1 显示,0 不显示asdeclare count int,s nvarchar(1000),i intselect ididentity(int,1,1),标志,进程IDspid,线程IDkp…

离群点检测算法-基础概念

定义&#xff1a; Hawkins给出的离群点的本质性定义&#xff1a;离群点是数据集中偏离大部分数据的数据&#xff0c;由于偏离其它数据太多&#xff0c;使人怀疑这些数据的偏离并非由随机因素产生&#xff0c;而是产生于完全不同的机制。 大致分类&#xff1a; 一例分析步骤&am…

17 性能测试

性能测试 前言性能测试性能测试的目标总结前言 系统级性能测试是验证系统做的好不好,进行性能测试的前提条件是系统做的是对的。 性能测试 系统级性能测试是为了发现系统性能问题或获取系统性能相关指标而进行的测试。一般在真实环境、特定负载条件下,通过工具模拟实际软件…