模数不超过 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命令重启服务,然 ...
随机推荐
- 自定义Push/Pop和Present/Dismiss转场
项目概述 iOS中最常见的动画无疑是Push和Pop的转场动画了,其次是Present和Dismiss的转场动画. 如果我们想自定义这些转场动画,苹果其实提供了相关的API,在自定义转场之前,我们需要 ...
- 兜底机制——leader到底做了什么?
Case 在之前一次年底考评的时候,有一位leader将一个案例同时用到了自己和下属身上,老板发出了责问: 这个项目到底你是负责人,还是你下面的同学是负责人,如果下面的同学是负责人,为什么要算到你的头 ...
- 项目优化之v-if
前言: 在vue项目中,由于功能比较多,需要各种条件控制某个功能.某个标签.表格中的某一行是否显示等,需要使用大量的v-if来判断条件. 例如: <div v-if="isShow(a ...
- JavaScript03
类型转换和运算符 typeof函数 检测数据类型,可以使用以下两种调用的方式: typeof 变量或表达式 typeof(变量或表达式) var n="asda"; console ...
- HTTP标签
系统的http状态码知识,我是在<图解http里学习的>. 状态码的职责是告知从服务器端返回的请求结果. 分类如下: 2XX --> 成功 200 OK(一般情况) 204 No C ...
- C# 如何使用代码添加控件及控件事件
1.首先简单设计一下界面: 添加了Click事件 <Window x:Class="WpfApp.MainWindow" xmlns="http://schemas ...
- BUAA2020软工团队beta得分总表
BUAA2020软工团队beta得分总表 [TOC] 零.团队博客目录及beta阶段各部分博客地址 团队博客 计划与设计博客 测试报告博客 发布声明博客 事后分析博客 敏 杰 开 发♂ https:/ ...
- 【二食堂】Alpha - Scrum Meeting 7
Scrum Meeting 7 例会时间:4.17 11:40 - 12:00 进度情况 组员 昨日进度 今日任务 李健 1. 继续文本区域的开发,先完成目前简陋的添加方式,再区实现勾选功能issue ...
- 热身训练2 GCD
题目描述 简要题意: n个数字,a1,a2,...,an m次询问(l,r),每次询问需回答 1.gcd(al,al+1,al+2,...,ar);2.gcd(ax,ax+1,ax+2,...,ay ...
- 洛谷 P3232 [HNOI2013]游走
链接: P3232 题意: 和上次考试 T4 的简化且无修改一样,经典图上高斯消元求期望. 分析: 要求出每个点的期望出发次数 \(f_i\),每个点度数为 \(d_i\),有 \[f1=\sum\d ...