C++_初识欧拉降幂_洛谷P5091

以下两张图片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/SP4141icon-default.png?t=O83Ahttps://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;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值