[位运算] 64位整数乘法(mod 一个数)

64位整数乘法

  在部分题目中可能涉及到长整数(long long)的相关计算,可当我们需要将两个长整数相乘时有可能出现溢出的情况,这时候通常需要进行高精度计算,可如果我们需要将两个长整数相乘并 mod 一个数时高精度计算也就不太方便了,这时我们需要一个优秀的算法让我们快速的计算出类似 a×b mod c 的数值

[算法描述(1)]

  我们用快速幂的思想,将b用二进制表示

b=ck-12k-1+ck-22k-2+…+c020

  那么:

 a×b=a×(ck-12k-1+ck-22k-2+…+c020)=a×ck-1×2k-1+a×ck-2×2k-2+…+a×c0×20

  又

a×2i=(a×2i-1)×2

  于是我们可以递推地计算出a×2i并且每次计算把答案加入ans中与快速幂不同的是ans的初始化并不是赋值为1而是清0.时间复杂度为O(log2 b).

  在此基础上我们考虑如果a,b是负数那怎么办呢?为了解决这个问题我们考虑打一个标记w,我们将w的初始值赋值为1,如果a,b的值是负数的话就把w值取w=-w(a,b均做一次判断),我们把返回ans×w即可.

  如果b的值远大于a时O(log2 b)这个时间复杂度相对于O(log2 a)而言就不是那么优秀了,于是我们可以进一步优化,如果a比b的数值小的话就交换a和b的数值,那么这个时间复杂度最终为O(log2 min(a,b))当然如果a,b均大于c时可以实现对a,b mod c进一步优化时间复杂度

[代码(1)]

/*
    Name: Multiplication
    Author: FZSZ-LinHua
    Date: 2018 06 07
    Time complexity: O(log min(a,b))
    Algorithm: Binary calculation
*/
# include "iostream"
# include "cstdio"

using namespace std;

long long mul(long long x,long long y,long long z){    //计算x*y mod z的数值
    long long ans=0;
    int w=1;
    if(y<0){    //如果y<0那么标记一下,y取绝对值
        w=-w;
        y=-y;
    }
    if(x<0){    //如果x<0那么标记一下,x取绝对值
        w=-w;
        x=-x;
    }
    if(x<y){    //如果x比y小那么交换x,y
        swap(x,y);
    }
    while(y){
        if(y&1){    //如果y的i位不为0就加入答案中
            ans=(ans+x)%z;
        }
        x=(x*2)%z;    //递推计算a^2i
        y>>=1;     //舍弃最低位
    }
    return w*ans;//返回答案
}

int main(){
    long long a,b,c;
    scanf("%lld%lld%lld",&a,&b,&c);
    printf("%lld",mul(a,b,c));
    return 0;
} 

[算法描述(2)]

  对于上述算法我们思考能不能用更短的时间内算出a×b mod c的数值呢?我们发现一个式子

a×b mod c=a×b-[a×b/c]×c([x]表示x下取整)

  我们可以先处理除[a×b/c]×c的数值,算ans时将a×b减去该数值即可,注意计算出的ans值可能为负数也可能大于c所以我们需要对ans加上c再mod c及(ans+c) mod c

[代码(2)]

/*
    Name: Multiplication
    Author: FZSZ-LinHua
    Date: 2018 06 07
    Time complexity: O(1)
    Algorithm: Brute-force
*/
# include "iostream"
# include "cstdio"

using namespace std;

long long mul(long long x,long long y,long long z){    //计算x*y mod z的数值
    long long a=(long double) x*y/z;
    long long ans=x*y-a*z;
    ans=(ans+z)%z;
    return ans;
}

int main(){
    long long a,b,c;
    scanf("%lld%lld%lld",&a,&b,&c);
    printf("%lld",mul(a,b,c));
    return 0;
} 

原文地址:https://www.cnblogs.com/FJ-LinHua/p/9152631.html

时间: 2024-10-13 05:42:37

[位运算] 64位整数乘法(mod 一个数)的相关文章

系统32位和64位的区别

32位和64位有什么区别呢? 什么时候安装32位的,又什么时候安装64位操作系统呢?如何查看系统是32位的还是64位的?       我们所谓的32位.64位指的是CPU的GPRs(General-Purpose Registers,通用寄存器)的数据宽度.64位的cpu较之32位可以进行更大范围的整数运算:可以支持更大的内存.不能因为数字上的变化,而简单的认为64bit处理器的性能是32bit处理器性能的两倍.实际上在32bit应用下,32bit处理器的性能甚至会更强,即使是64bit处理器,

Java千百问_01基本概念(016)_32位和64位计算机有什么区别

点击进入_更多_Java千百问 1.32位和64位计算机有什么区别 我们通常说的32位.64位计算机是指计算机的CPU位数.当然很早还有8位.16位的CPU,以Intel的80x86系列来说,8位的8080,16位的8086.8088.80186.80286,而32位的CPU最早始于80386,64位就是大家熟悉的EM64T技术以及AMD的x86-64.当然不同的厂商间同位数的CPU内部有很大的区别,但是它们的核心都是一样:CPU处理能力为64位. 这个位数指的是CPU的通用寄存器(GPRs,G

iOS开发——实战总结&amp;32位升64位的变化

32位升64位的变化 终究还是来了.Apple下发了支持64位的最后通牒: As we announced in October, beginning February 1, 2015 new iOS apps submitted to the App Store must include 64-bit support and be built with the iOS 8 SDK. Beginning June 1, 2015 app updates will also need to fol

判断应用程序是32位还是64位

VC++检测可执行程序DLL.EXE等是32位还是64位 1.首先介绍PE结构 Windows系统下的可执行文件,是基于Microsoft设计的一种新的文件结构,此结构被称之为PE结构.PE的意思是Portable Executable(可移植的执行体),所有Win32执行体都是用PE文件格式,其中包括SYS.DLL.EXE.COM.OCX等.(不管是学习逆向.破解还是安全,了解PE文件格式都是非常必要的.) PE文件的第一个部分是IMAGE_DOS_HEADER,大小为64B,这里面有两个重要

iOS 32位、 64位系统兼容性设置-Xcode创建支持IOS4.3以上版本的应用的方法

方法一: 如果是Xcode 5的话步骤为 点击项目名称->Build Settings->搜索 Architectures 这个里面的原始的值是Standard architectures(armv7,armv7s,arm64) 点击这个值,在下拉列表框中选择 Standard architectures(armv7,armv7s) ,然后保存项目,转到 General里面去就可以看到项目的Target选项里面会从4.3到7.0都有. 如果是Xcode 5.1的话步骤为 点击项目名称->

CentOS 5 上使用yum同时安装32位和64位包的解决方法

在centos上使用yum在线安装软件包的时候,有时候会同时安装32位和64位的包.并且在update的时候也会更新双份. 其实让yum只安装64位的包,只要在 /etc/yum.conf 中加个 exclude 选项: [main] cachedir=/var/cache/yum keepcache=0 plugins=1 ...... exclude=*.i?86 exclude 选项支持正则表达式,*.i?86可以用来过滤掉i386,i686等32bit包. 如果要删除已经安装的32bit

驱动级多开工具,支持32位和64位

标题:[原创]驱动级多开工具,支持32位和64位 作者:绿林科技 时间:2015-5-16 链接:http://blog.csdn.net/o6108/article/details/47790019 作者QQ:1473656864 技术交流群1:177822108 技术交流群2:177822398 通用驱动级多开器,可多开市面上的90%的程序. PS:本来想弄个收费版本的,后来想了想,决定弄成免费.店铺为更新软件版本用的. 软件的About页面有我的QQ和Q群号,请大家把使用过程中遇到的BUG

如何查看eclipse是32位还是64位

如何查看eclipse是32位还是64位? 1.如果是在官网下载的,看压缩包名字就可以看出来,只带有win32字样的是32位,带有win32-x86_64字样的是64位的. 如果已经安装了很多,安装包已经找不到了怎么办呢? 2.找到eclipse安装目录的eclipse.ini文件打开,在launcher.library项下,如果是win32.x86则是32位的,如果是win32.x86_64则是64位的. -startup plugins/org.eclipse.equinox.launche

iOS-程序发布-32位和64位系统的兼容

在苹果推出iPhone5S时,64位的应用就走到了眼前.当时就看见苹果官方资料宣布iOS7.x的SDK支持了64位的应用,而且内置的应用都已经是64位. 我记得自己刚刚接触电脑时还有16位的系统,指针的寻址范围还是16位的.当年用TurboC时,还要根据应用的大小选择是tiny模式还是其他.后来很长一段时间使用32位的模型编程,4G是牢牢记住的一个边界条件.而现在,64位走到了眼前. 就如同16位转向32位一样,硬件肯定是最先推出的,SDK也会跟进,然后各种第三方的应用才会逐步跟进,这个过程一般