模数不超过 long long 范围时的快速乘
笔者的话:使用前请确保评测系统的long double严格为16B !
模数不在 int 范围内的乘法在 OI 中运用广泛,例如Millar-Rabin,Pollard-Rho等等。这样的乘法,直接乘惨遭 long long 溢出, WA 声一片。冒险运用 __int128 ,一朝事发,倾家荡产。误食 $O(\log P)$ 的龟速乘,人傻常数大, TLE 也无处申诉。这个时候, $O(1)$ 的快速乘就能派上用场。
快速乘运用真正的long double解决这样的一个问题:给定 $x,y,P$ 满足 $0\le x,y<P$ ,计算 $xy\bmod P$ 。这里 $P< 2^{63}$ 。注意 $P$ 不一定是质数。
首先分析取模, $xy\bmod P=xy-\lfloor\frac{xy}{P}\rfloor P=(xy-\lfloor\frac{xy}{P}\rfloor P) \bmod 2^{64}$ 。所以,算出 $\lfloor\frac{xy}{P}\rfloor$ 后可以巧妙地借助自然溢出计算左右两个乘法和中间的减法,得到该式对 $2^{64}$ 取模的结果,也就得到了该式。
于是我们只剩下了一个难点就是计算 $\lfloor\frac{xy}{P}\rfloor$ 。这肯定不能先乘再除,只能先除再乘再取整。考虑搬出16B 的 long double ,先除再乘。
既然运用了 long double ,无疑这会有精度误差。极端情况是 $\frac{x}{P}$ 的第一个有效位在小数点后第一位,那么 long double 从第六十五位开始出错,因此误差范围在 $(-2^{-64},2^{-64})$ ,乘 $y$ 之后就为 $(-\frac{1}{2},\frac{1}{2})$ 。运用常见技巧将其加上0.5L,误差范围变为 $(0,1)$ 。于是,取整时误差为 $0,1$ 之一,乘 $-P$ 以后,最终误差为 $0,-P$ 之一。也就是说,设答案为 $a$ ,最后的计算结果 $r$ 为 $a-P,a$ 之一。
由于 P 在 long long 内,所以当 $0\le r<P$ 时其为第二类,直接返回 $r$ ,否则为第一类,返回 $r-P$ ,就完成了快速乘计算。时间比较充裕的话直接返回 $(r+P)\bmod P$ 即可。
经实测,在笔者笔记本电脑上,开启O2进行1e8次此数据范围内的乘法运算,快速乘耗时 6.248s ,而龟速乘耗时 55.043s ,并且计算结果相同,足以见得快速乘的优越性。
附代码:
快速乘
typedef unsigned long long ll;
ll mul(ll x,ll y,ll P){ll z=x*y-(ll)((long double)x/P*y+0.5L)*P;return z<P?z:z+P;}
龟速乘
typedef unsigned long long ll;
ll mul(ll x,ll y,ll P){ll z=0;for(;y;(x<<=1)>=P&&(x-=P),y>>=1)y&1&&((z+=x)>=P&&(z-=P));return z;}
模数不超过 long long 范围时的快速乘的更多相关文章
- Easyui datagrid 设置内容超过单元格宽度时自动换行显示
datagrid 设置内容超过单元格宽度时自动换行显示 by:授客 QQ:1033553122 测试环境 jquery-easyui-1.5.3 问题描述 单元格内容超过单元格宽度不会自动化换行.如下 ...
- gvim写html代码时如何快速地跳转到一个标签的结束位置: 终极插件: matchit.vim
gvim写html代码时如何快速地跳转到一个标签的结束位置 参考这个vimrc的配置, 里面有一些 很好的东西, 配置很有用, 以前没有用到: http://www.cnblogs.com/wangj ...
- 如何固定OpenERP顶的主菜单,方便滚动至第二屏以及多屏时,快速切换主菜单
如何固定OpenERP顶的主菜单,方便滚动至第二屏以及多屏时,快速切换主菜单 作者:广州-步科,来自OpenERP应用群() 将“addons\web\static\src\css”目录下的“base ...
- m_Orchestrate learning system---二十七、修改时如何快速找到作用位置
m_Orchestrate learning system---二十七.修改时如何快速找到作用位置 一.总结 一句话总结:找人,找起作用的位置真的重要,找到就事半功倍了 加载页面的时候观察在f12的e ...
- 小记:Quartz 当 Job 执行时间超过触发间隔时间时所发生的情况
一个普通的 Job 实现如下: public class Job1 : IJob { public void Execute(IJobExecutionContext context) { Conso ...
- Redis持久化磁盘IO方式及其带来的问题 有Redis线上运维经验的人会发现Redis在物理内存使用比较多,但还没有超过实际物理内存总容量时就会发生不稳定甚至崩溃的问题,有人认为是基于快照方式持
转自:http://blog.csdn.net/kaosini/article/details/9176961 一.对Redis持久化的探讨与理解 redis是一个支持持久化的内存数据库,也就是 ...
- 解决git push时发现有超过100M的文件时,删除文件后,发现还是提交不上去的问题
我这里故意放了一个超过100M的文件 后续,git add ,git commit 然后,git push 此时会发现出现了错误.如果,我们再这里直接在文件系统中删除这个大的文件,然后再次提交,会发现 ...
- Vue:列表展开和收起(超过一定行数时显示‘查看更多’按钮)
前言:前端小白记录的一些小功能~ 公司开发中的小程序中有做任务签到的功能,这就涉及到了任务列表以及对任务列表的展开和收起功能,好了可以开始了,说多了就烦了 1.首先是css样式,因为设计稿上是超过两行 ...
- NodeJs使用Express框架开发时的快速调试方法
习惯了php开发,可以直接使用echo或者var_dump()将想要查看的变量结果输出到网页查看,非常的方便.但是使用express开发时,每次修改文件后,都需要使用npm start命令重启服务,然 ...
随机推荐
- python os.walk处理树状目录结构的文件
在项目工作中,时常需要用到处理文件的方法,尤其是在windows环境下的树状目录结构 os.walk恰好能完美的处理这种树状目录结构文件,能高效地帮助我们得到我们需要处理的文件 目录结构: Deskt ...
- 【UE4 设计模式】命令模式 Command Pattern
概述 描述 将一个请求封装为一个对象,从而使我们可用不同的请求对客户进行参数化:对请求排队或者记录请求日志,以及支持可撤销的操作. 命令模式是一种对象行为型模式,其别名为动作(Action)模式或事务 ...
- 395.至少有 K 个重复字符的最长子串
题目 给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于k .返回这一子串的长度. 示例 1: 输入:s = "aaabb" ...
- Java:static关键字小记
Java:static关键字小记 对 Java 中的 static 关键字,做一个微不足道的小小小小记 static 修饰变量 静态变量:是被 static 修饰的变量,也称为类变量,它属于类,因此不 ...
- 5.31日 Scrum Metting
日期:2021年5月31日 会议主要内容概述:讨论草稿箱前后端接口,讨论账单页面设计. 一.进度情况 组员 负责 两日内已完成的工作 后两日计划完成的工作 工作中遇到的困难 徐宇龙 后端 文件导入功能 ...
- SpringCloud 2020.0.4 系列之服务降级
1. 概述 老话说的好:做人要正直,做事要正派,胸怀坦荡.光明磊落,才会赢得他人的信赖与尊敬. 言归正传,之前聊了服务间通信的组件 Feign,今天我们来聊聊服务降级. 服务降级简单的理解就是给一个备 ...
- [hi3521] nand flash 的 boot 启动模式的区别?
spi nand flash 的 boot 启动模式选择.0:1 线 boot:1:4 线 boot.请问,1线boot和4线boot有什么区别呢?该如何选择呢? 收藏 顶 踩 回复 使用 ...
- hdu 3635 Dragon Balls(并查集)
题意: N个城市,每个城市有一个龙珠. 两个操作: 1.T A B:A城市的所有龙珠转移到B城市. 2.Q A:输出第A颗龙珠所在的城市,这个城市里所有的龙珠个数,第A颗龙珠总共到目前为止被转移了多少 ...
- hdu 5185 Equation(分析+DP)
题意: Gorwin is very interested in equations. Nowadays she gets an equation like thisx1+x2+x3+⋯+xn=n, ...
- Oracle日志 归档模式管理
一.查看当前归档模式 archive log list; 二.归档/不归档切换 shutdown immediate; -- 或shutdown normal startup mount; alter ...