怎么还有厉害的在线O(1)求逆元,不过常数确实有点儿太大了

本文大部分搬运于这里

相信大家都做过 POJ2478 这道题吧,这道题的 Farey 序列 \(F_n\) 包含了分子分母不大于 \(n\) 且互质的数。该分数可以为 \(0\) 和 \(1\)。

嗯我们现在要把 \(F_{\sqrt [3]p}\)求出来,然后有一个妙妙定理,就可以在线地 \(O(1)\) 求逆元。

定理:给定一个分数 $\frac a b(0 \leq \frac a b \leq 1) $和一个 $ n(n > 1)$,你都可以在 \(F_{n-1}\) 中找到一个分数使得 \(|\frac a b-\frac x y| \leq \frac 1 {yn}\),并且这个分数一定是 \(\frac a b\) 在序列中使用 useful binary search 后往前或往后的第一个数。

证明?注意到 \(F_{n-1}\) 实际上包含了分子分母都不大于 \(n\) 的所有分数,只不过将其去重了。所以我们对每一个分母都讨论一遍。

差不多就是要证明对于所有不大于 \(n\) 的数对 \((x,y)\),\([\frac x y-\frac 1 {ny},\frac x y+\frac 1 {ny}]\) 的并包含了 \([0,1]\)。也就是对于任意一个区间,一定有另一个在其右侧区间与其相交。

通分:\([\frac {nx-1} {ny},\frac {nx+1} {ny}]\)。

那么我们接下来需要证明对于 \(x_1<y_1\) 一定有 \(x_2<y_2\) 满足 \(\frac {x_1}{y_1} \ne \frac {x_2}{y_2}\) 且 \(\frac {nx_1+1}{ny_1}>\frac {nx_2-1}{ny_2}\)。

还是通分:\(nx_1y_2+y_2>nx_2y_1-y_1\),也就是 \(y_1+y_2>n(x_2y_1-x_1y_2)\)。很明显一定有 \(x_2=x_1-1,y_2=y_1-1\) 满足条件。

啥?\(x_1=0,y_1=1\)?右端点为 \(\frac 1 n\),那么存在 \(\frac 1 {n-1}\) 满足 \(\frac 1 {n-1} - \frac 1 {n(n-1)}=\frac 1 n\)。

所以自然就是二分查找后向前或向后的第一个数。

以上内容均为口胡

我们发现这个结论 \(|\frac a b - \frac x y| \leq \frac 1 {yn}\),通分之后就是 \(| ay-bx | \leq \lfloor \frac b n \rfloor\)。这里把 \(b\) 用 \(p\) 替换一下。

上面的结论相当于 \(ay \equiv t \pmod p\),且 \(t \leq \lfloor \frac p n \rfloor\),相当于 \(a^{-1} \equiv yt^{-1} \pmod p\)。

所以只需要找到这个分数之后,处理 \(t\) 的逆元就好了啊。

因为 \(t \leq \lfloor \frac p n \rfloor\),我们预处理一个长度为 \(n\) 的 Farey 肯定需要至少 \(O(n^2)\) 的时间,\(n^2=\frac p n\),得到 \(n=\sqrt [3]p\)。所以需要预处理 \(F_{\sqrt [3]p}\) 和 \(p^{\frac 2 3}\) 以内的数的逆元。

那么如何 \(O(n^2)\) 预处理 Farey 序列和 \(O(1)\) 二分查找?

我们可以请教神圣二分帝国皇帝 Um_nik

对于 Farey 序列中的任意两个数 \(\frac {x_1}{y_1}\) 和 \(\frac {x_2}{y_2}\),有 \(\frac {x_1}{y_1}-\frac {x_2}{y_2}=\frac {x_1y_2-x_2y_1}{y_1y_2}\)。在分母最大的情况下不大于 \(p^{\frac 2 3}\),分子最小不小于 \(1\),所以只需要将原分数乘上 \(p^{\frac 2 3}\) 后向下取整,一定互不相同。

所以只需要把 \(\frac x y\) 映射到 \(\lfloor \frac {x \times p^{\frac 2 3}} y \rfloor\) 后桶排序就可以啦。

代码压过行,还卡过常,实际上写起来也不是很长。

目测常数是正常离线求逆的 \(2 \sim 3\) 倍。

#include<iostream>
#include<cctype>
#include<cmath>
typedef unsigned ui;
typedef __uint128_t L;
typedef unsigned long long ull;
const ui M1=1000,M2=M1*M1;
ui T,m1,m2,MOD,len,fra[M2+5],inv[M2+5],sum[M2+5];
ui q[M2+5];ull p[M2+5];
double invm1,INV;
char buf[1<<22|1],*p1=buf;
inline char Getchar(){
return*p1=='\0'&&(std::cin.read(p1=buf,1<<22)),*p1++;
}
struct FastMod{
ull b,m;
FastMod(ull b):b(b),m(ull((L(1)<<64)/b)){}
friend inline ull operator%(const ull&a,const FastMod&mod){
ull r=a-(L(mod.m)*a>>64)*mod.b;
return r>=mod.b?r-mod.b:r;
}
}mod(2);
inline ull abs(const ull&a){
return a>>63?-a:a;
}
inline ui read(){
ui n(0);char s;
while(!isdigit(s=Getchar()));
while(n=n*10+(s&15),isdigit(s=Getchar()));
return n;
}
inline void init(){
ui i,j,x;
for(i=1;i^m1;++i){
const double&INV=1./i+1e-15;
for(j=0;j^i;++j)if(!sum[x=1ull*j*m2*INV])sum[x]=1,fra[x]=m1*i+j;
}
for(i=0;i<=m2;++i){
if(sum[i])++len,q[len]=fra[i]*invm1,p[len]=1ull*(fra[i]-q[len]*m1)*MOD;
if(i)sum[i]+=sum[i-1];inv[i]=i>1?1ull*(MOD-MOD/i)*inv[MOD%i]%mod:i;
}
}
inline ui Inv(const ui&a){
static ui q,k;static ull t;
if(a<=m2)return inv[a];if(MOD-a<=m2)return MOD-inv[MOD-a];k=sum[ui(a*INV)];
if(k<=len){
q=::q[k];t=1ull*a*q-p[k];
if(abs(t)<=m2)return 1ull*q*(t>>63?MOD-inv[-t]:inv[t])%mod;
}
if(++k<=len){
q=::q[k];t=1ull*a*q-p[k];
if(abs(t)<=m2)return 1ull*q*(t>>63?MOD-inv[-t]:inv[t])%mod;
}
return-1;
}
signed main(){
std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
ui k,x,sum(0);T=read();MOD=read();mod=FastMod(MOD);x=k=read();
m1=pow(MOD,1./3)+1;m2=m1*m1;invm1=1./m1+1e-15;INV=1.*m2/MOD+1e-15;init();
while(T--)sum=(sum+1ull*x*Inv(read()))%mod,x=1ull*x*k%mod;std::cout<<sum;
}

在线O(1)求逆元的更多相关文章

  1. CF451E Devu and Flowers (隔板法 容斥原理 Lucas定理 求逆元)

    Codeforces Round #258 (Div. 2) Devu and Flowers E. Devu and Flowers time limit per test 4 seconds me ...

  2. 【板子】gcd、exgcd、乘法逆元、快速幂、快速乘、筛素数、快速求逆元、组合数

    1.gcd int gcd(int a,int b){ return b?gcd(b,a%b):a; } 2.扩展gcd )extend great common divisor ll exgcd(l ...

  3. 【BZOJ-4522】密钥破解 数论 + 模拟 ( Pollard_Rho分解 + Exgcd求逆元 + 快速幂 + 快速乘)

    4522: [Cqoi2016]密钥破解 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 290  Solved: 148[Submit][Status ...

  4. hdu 1576 求逆元

    题意:给出n=A mod 9973和B,求(A/B) mod 9973 昨天用扩展欧几里得做过这题,其实用逆元也可以做. 逆元的定义:例如a*b≡1 (mod m),则b就是a关于m的逆元. 求逆元方 ...

  5. HDU4869:Turn the pokers(快速幂求逆元+组合数)

    题意: 给出n次翻转和m张牌,牌相同且一开始背面向上,输入n个数xi,表示xi张牌翻转,问最后得到的牌的情况的总数. 思路: 首先我们可以假设一开始牌背面状态为0,正面则为1,最后即是求ΣC(m,k) ...

  6. ZOJ 3609 求逆元

    Modular Inverse Time Limit: 2 Seconds      Memory Limit: 65536 KB The modular modular multiplicative ...

  7. codeforces 492E. Vanya and Field(exgcd求逆元)

    题目链接:codeforces 492e vanya and field 留个扩展gcd求逆元的板子. 设i,j为每颗苹果树的位置,因为gcd(n,dx) = 1,gcd(n,dy) = 1,所以当走 ...

  8. 51NOD 1258 序列求和 V4 [任意模数fft 多项式求逆元 伯努利数]

    1258 序列求和 V4 题意:求\(S_m(n) = \sum_{i=1}^n i^m \mod 10^9+7\),多组数据,\(T \le 500, n \le 10^{18}, k \le 50 ...

  9. 51nod 1118 机器人走方格 解题思路:动态规划 & 1119 机器人走方格 V2 解题思路:根据杨辉三角转化问题为组合数和求逆元问题

    51nod 1118 机器人走方格: 思路:这是一道简单题,很容易就看出用动态规划扫一遍就可以得到结果, 时间复杂度O(m*n).运算量1000*1000 = 1000000,很明显不会超时. 递推式 ...

随机推荐

  1. JSP中获取各种路径的方法

    我们当中可能有很多人不知道如何获得jsp中的路径怎么获取 方法一: <a href ="test.jsp?p=fuck">跳转到test2</a> 方法二: ...

  2. Visual Studio 下error C2471: 无法更新程序数据库

    转载请注明来源:https://www.cnblogs.com/hookjc/ 解决方案:修改项目属性 右击项目 --> "属性" 1. "C/C++" ...

  3. 数组中包含多个对象 按照对象中的时间进行排序 适用与Angular.js、Jquery、微信小程序等

         LiveList.sort(this.compare('StartDate'))   //StartData:需要排序的时间   compare: function (property) { ...

  4. AI模型运维——GPU性能监控NVML和DCGM

    最近一年负责运维的GPU主机越来越多,发现现有的监控项无法很好的了解GPU的性能和负载情况,研究了下官方文档,在此记录. 一.NVML和DCGM NVML:https://developer.nvid ...

  5. docker基础——5.Dockerfile

    把应用部署在容器中,改变了用文本文件保存配置信息的方式.而通过传环境变量配置. Dockerfile是一个文本文件,包括容器的指令.按顺序从上到下执行,第一行非注释指令必须是FROM指定基础镜像. D ...

  6. git忽略项目中的指定文件

    git仓库提交原则:提交给远程仓库的只有源代码和相关的配置文件 如果是使用模板建立的仓库,会自带有.gitignore文件,无需再建立.当然如果需要在指定文件忽略,只需要在这个文件中添加指定的文件即可 ...

  7. nginx负载均衡中常见的算法及原理有哪些?

    一.nginx负载均衡常用算法 1.1 轮询 轮询,nginx默认方式.一次将请求分配给各个后台服务器. upstream backserver { server 10.0.0.7; server 1 ...

  8. Solution -「NOI.AC 省选膜你赛」union

    题目 题意简述   给定两颗树 \(A,B\),\(A\) 中的任一结点 \(u\) 与 \(B\) 中的任一结点 \(v\) 都有一个关系值 \(f(u,v)\),初始为 \(0\).再给出 \(q ...

  9. NTFS ADS(备用数据流)

    NTFS Alternate Data Stream(ADS)   1993年微软推出了基于流行的NT平台的Windows NT操作系统.之后,NTFS作为WIndows开发基于NT的操作系统时的首选 ...

  10. 第三章 in,not in 的理解,limit限制结果集

     IN 运算符用来判断表达式的值是否位于给出的列表中:如果是,返回值为 1,否则返回值为 0.NOT IN 的作用和 IN 恰好相反,NOT IN 用来判断表达式的值是否不存在于给出的列表中:如果不是 ...