cinta作业3:同余与模运算、费马小定理、欧拉定理

1、求乘法逆元以及求解同余方程ax = b mod m

具体题目如下:
实现求乘法逆元的函数,给定a和m,求a模m的乘法逆元,无解时请给出无解提示,并且只返回正整数。进而给出求解同余方程(ax = b mod m)的函数,即给定a,b,m,输出满足方程的x,无解给出无解提示。

下面程序均假设egcd函数已经实现

1.1 求乘法逆元

//实现求乘法逆元的函数
#include <iostream>
using namespace std;
int multi_inverse (int a, int m);

int main()
{
	int a, m;
	cin >> a >> m;
	int Multi_Inverse = multi_inverse(a, m);
	if (Multi_Inverse == -1)
		cout << "无解" << endl;
	else
		cout << "逆元是" << Multi_Inverse;
}

//求a模m的乘法逆元
int multi_inverse (int a, int m)
{
	int s, t;
	//gcd(a,m)!=1 无解
	if (egcd(a, m, &s, &t) != 1)
	{
		return -1;
	}

	//gcd(a,m)=1  此时有解,且逆元取决于a前面的系数
	else
	{
		//又基于egcd函数会将大的输入数与s系数配对,小的输入数反之则与t配对,下面进行对a和m判断大小

		if (a > m) //此时s即是a前面的系数
		{
			if (s < 0)
				s = s + m;//根据逆元定义:负数要转化为正数
			return s;
		}
		else       //对此时t即是a前面的系数
		{
			if (t < 0)
				t = t + m;
			return t;
		}
	}
}

1.2 求解同余方程

#include <iostream>
using namespace std;
int solve_CongruenceEquation(int a, int b, int m);

int main()
{
	int a, b, m;
	cin >> a >> b >> m;
	int x = solve_CongruenceEquation(a, b, m);
	if (x == -1)
		cout << "无解";
	else
		cout << "解为" << x;
}

//求解同余方程(ax = b mod m)的函数
int solve_CongruenceEquation(int a, int b, int m)
{
	int x, y;
	int gcd_a_m = egcd(a, m, &y, &x); //gcd(a,m)

	//gcd(a,m)|b不成立,无解
	if ((b % gcd_a_m) != 0)
	{
		return -1;
	}
	//gcd(a,m)|b 成立
	else
	{
		return x / gcd_a_m * b;//这里输出的仅是其中一个特解
	}
}

2、模指数运算

实现模指数运算的函数,给定x、y和m,求x的y次方模m。

//实现模指数运算的函数
#include <iostream>
using namespace std;
int mod_exp(int x, int y, int p);

int main()
{
	int x, y, p;
	cin >> x >> y >> p;
	cout << mod_exp(x, y, p);
}

int mod_exp(int x, int y, int p)
{
	int result = 1;
	while (y > 0)
	{
		if ((y & 1) == 1) //判断最后一个bit为1
		{
			result = (result * x) % p;
		}
		y >>= 1; //乘除2都用位运算,效率高
		x = (x * x) % p;
	}
	return result;
}

3. 费尔马小定理

题目如下:

设p = 23和a = 5,使用费尔马小定理计算a^{2020} mod p

因为 p = 23 p=23 p=23是素数,由费马小定理可得 5 22 ≡ 1 ( m o d 23 ) 5^{22}\equiv 1 (mod 23) 5221(mod23)
又因为 5 2020 = 5 91 ∗ 22 + 18 5^{2020} =5^{91*22+18} 52020=59122+18,则 5 2020 5^{2020} 52020 mod 23 = 5 18 23=5^{18} 23=518 mod 23 = 6 23=6 23=6

4. 欧拉定理

题目如下:

使用欧拉定理计算2^{100000} mod 55

55=5*11,5、11均为素数,则 Φ ( 55 ) = ( 5 − 1 ) ( 11 − 1 ) = 40 \Phi(55)=(5-1)(11-1)=40 Φ(55)=(51)(111)=40
由欧拉定理可得 2 40 2 ^ {40} 240 mod 55 = 1
因此 2 100000 2^{100000} 2100000mod 55 = 2 2500 ∗ 40 2^{2500*40} 2250040mod 55 = 1

5. 手动计算7^{1000}的最后两个数位等于什么?

这里我们将题目转化为求 7 1000 7^{1000} 71000 mod 100 ,这样我们便可以用欧拉定理进行求解:

因为 100 = 5 2 × 2 2 100=5^{2}\times 2^{2} 100=52×22 Φ ( 100 ) = 100 ( 1 − 1 / 5 ) ( 1 − 1 / 2 ) = 40 \Phi(100)=100(1-1/5)(1-1/2)=40 Φ(100)=100(11/5)(11/2)=40
由欧拉定理可得 7 40 7 ^ {40} 740 mod 100 = 1, 因此 7 1000 7^{1000} 71000mod 100 = 7 25 ∗ 40 7^{25*40} 72540mod 100 = 1
从而得到7^{1000}的最后两个数位等于01

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GOAT_0x02

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值