以下两张图片From : 欧拉降幂 - 爱吐水的小火龙 - 博客园,作者认为相当易懂了
不知道什么叫“扩展欧拉”,读了很长时间的数论知识背景,靠着高中数学水平也很难接受!
本文针对上题,提供简单的解法,记录几个数论结论,不涉及大量理论推演
要求在模m意义下的a的b次方(后记作 a^b %m),如果使用快速幂算法,b太大,无法用任何整数数据类型保存(比如无法用long long保存),使用上述欧拉降幂的结论,可以将
a^b %m
转化为
a^r %m 其中,r = b%φ(m),(此后 φ(m) 记作 phi_m),r 的范围进入0至m-1,可以用int保存,当然用long long也行
注意 当r=0时,上述结论 : a^b %m = a^r %m不成立,此时 a^b %m = a^phi_m %m
先求phi_m,即写出欧拉函数,请参考以下的第一篇题解:
https://www.luogu.com.cn/problem/solution/SP4141
https://www.luogu.com.cn/problem/solution/SP4141
我的欧拉函数:
int elfun(int x)
{
int ans=x;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
ans-=ans/i;
while(x%i==0)
{
x=x/i;
}
}
}
if(x>1)
ans-=ans/x;
return ans;
}
然后需要求 b%phi_m,此时b太大无法用任何整数类型保存,所以需要用到大数取模的方法,不作证明,过程如下:
以123456789 % 9为例(虽然123456789不算是大数,但是操作过程是一样的)
0*10+1=1 1%9 = 1
1*10+2 =12 12%9=3
3*10+3=33 33%9=6
6*10+4=64 64%9=1
1*10+5=15 15%9=6
6*10+6=66 66%9=3
3*10+7=37 37%9=1
1*10+8=18 18%9=0
0*10+9=9 9%9=0
答案取最后一个模的结果,即0
大概描述一下,就是从高位到低位,之前的模的结果乘10(起初模的结果是0),再加上这一位的数,再取模
写成函数如下:
// 计算字符串 b 对 m 的模
long long mod_large_num(const string &b, long long m) {
long long res = 0;
for (char digit : b) {
res = (res * 10 + (digit - '0')) % m; // 逐位计算
}
return res;
}
现在r算出来了,a也有了,使用快速幂 计算a^r 即可
快速幂:
// 快速幂算法
long long binpow(long long x, long long y, long long m) {
long long res = 1;
x = x % m; // 先对 x 取模(可去)
while (y) {
if (y & 1) {
res = (res * x) % m; // 如果 y 是奇数
}
x = (x * x) % m; // x 平方
y >>= 1; // 右移一位,相当于除以 2
}
return res;
}
应用:
603

被折叠的 条评论
为什么被折叠?



