【学习笔记】数学知识-基本数论算法
快速幂
- 例题
- luogu P1226 【模板】快速幂
-
已知 \(b\) 在二进制表示下有 \(\left\lceil \log_{2}{(b+1)} \right\rceil\) 位,设 \(c_i\) 表示其中第 \(i(1 \le i \le \left\lceil \log_{2}{(b+1)} \right\rceil)\) 位的数字,且 \(c_i \in [0,1]\),那么有 \(b=\sum\limits_{i=1}^{\left\lceil \log_{2}{(b+1)} \right\rceil}c_i 2^{i-1}\) ,于是有 \(a^b=a^{\sum\limits_{i=1}^{\left\lceil \log_{2}{(b+1)} \right\rceil}c_i 2^{i-1}}\) 。又因为 \(a^{2^i}=(a^{2^{i-1}})^2\) ,遍历 \(b\) 在二进制表示下的 \(\left\lceil \log_{2}{(b+1)} \right\rceil\) 位中满足 \(c_i=1\) 的即可。
-
时间复杂度为 \(O(\log_{2}{b})\)。
点击查看代码
ll qpow(ll a,ll b,ll p) { ll ans=1; while(b>0) { if(b&1) { ans=ans*a%p; } b>>=1; a=a*a%p; } return ans; } int main() { ll a,b,p; cin>>a>>b>>p; cout<<a<<"^"<<b<<" mod "<<p<<"="<<qpow(a,b,p); return 0; }
-
- luogu P5035 金坷垃 | AT_atc002_b n^p mod m | UVA374 Big Mod | UVA1230 MODEX | SP3442 LASTDIG - The last digit | SP9494 ZSUM - Just Add It
- luogu P1226 【模板】快速幂
龟速乘
- 例题
-
SP26368 PWRANDMOD - Power and Mod
- 已知 \(b\) 在二进制表示下有 \(\left\lceil \log_{2}{(b+1)} \right\rceil\) 位,设 \(c_i\) 表示其中第 \(i(1 \le i \le \left\lceil \log_{2}{(b+1)} \right\rceil)\) 位的数字,且 \(c_i \in [0,1]\),那么有 \(b=\sum\limits_{i=1}^{\left\lceil \log_{2}{(b+1)} \right\rceil}c_i 2^{i-1}\) ,于是有 \(a \times b=a \times {\sum\limits_{i=1}^{\left\lceil \log_{2}{(b+1)} \right\rceil}c_i 2^{i-1}}\) 。又因为 \(a \times 2^i=a \times 2^{i-1} \times 2\) ,遍历 \(b\) 在二进制表示下的 \(\left\lceil \log_{2}{(b+1)} \right\rceil\) 位中满足 \(c_i=1\) 的即可。
-
时间复杂度为 \(O(\log_{2}{b})\)。
点击查看代码
ll read() { ll x=0,f=1; char c=getchar(); while(c>'9'||c<'0') { if(c=='-') { f=-1; } c=getchar(); } while('0'<=c&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x*f; } void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x>9) { write(x/10); } putchar((x%10)+'0'); } ll smul(ll a,ll b,ll p) { ll ans=0; while(b>0) { if(b&1) { ans=(ans+a)%p; } b>>=1; a=(a+a)%p; } return ans; } ll qpow(ll a,ll b,ll p) { ll ans=1; while(b>0) { if(b&1) { ans=smul(ans,a,p); } b>>=1; a=smul(a,a,p); } return ans; } int main() { ll t,a,b,p,i; t=read(); for(i=1;i<=t;i++) { a=read(); b=read(); p=read(); write(qpow(a,b,p)); cout<<endl; } return 0; }
-
快速乘
- 例题
- luogu P10446 64位整数乘法
-
容易有 \(a \times b \bmod p=a \times b-\left\lfloor\dfrac{ab}{p}\right\rfloor \times p\) 。接着借助
unsigned long long
和long double
实现即可。 另外,因精度误差,最后得到的结果可能为负数,这就需要 \(+p\) 使之变为整数。- 快速乘误差较大,请谨慎使用。
-
时间复杂度为 \(O(1)\) 。
点击查看代码
ll qmul(ll a,ll b,ll p) { return ((ull)((ull)a*b-(ull)(1.0L*a/p*b+0.5L)*p)+p)%p; } int main() { ll a,b,p; cin>>a>>b>>p; cout<<qmul(a,b,p)<<endl; return 0; }
-
- luogu P10446 64位整数乘法
本文来自博客园,作者:hzoi_Shadow,原文链接:https://www.cnblogs.com/The-Shadow-Dragon/p/17640982.html,未经允许严禁转载。
版权声明:本作品采用 「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0) 进行许可。