数论:同余、模指数、费尔马小定理、欧拉定理
1、实现求乘法逆元的函数,给定a和m,求a模m的乘法逆元。无解时请给出无解提示,并且只返回正整数。进而给出求解同余方程(ax≡b mod m)的函数,即给定 a,b,m,输出满足方程的x,无解给出无解提示。
代码----乘法逆元的函数
#include<cmath>
int GCD(int x,int y); //return GCD(x,y)
bool Primer01(int a); //a is primmer number,return 1; return 0 if not
//默认m为素数
//input a、m //a mod m
//output x //满足a*x三 1 (mod m)
int M_I (int a,int m) //multiplicative inverse
{
if(GCD(a,m)!=1) return 0;
//利用费尔马小定理
//参考 https://www.cnblogs.com/-citywall123/p/10673212.html
if(Primer01(m)==1) return pow(a,m-2);
else return 0;
}
int main()
{
int a,m;
cin>>a,m;
if(M_I(a,m)==0) cout<<"无解!\n";
else cout<<M_I(a,m)<<endl;
return 0;
}
代码----求解同余方程(ax=b mod m)的函数
ax≡b mod m //①
构造m | ((a/b)*x-1) //×b 满足 ①式
求x,即求a/b mod m 的逆元
//上文的求逆元函数
int M_I(int a,int m); //return multiplicative inverse of a mod m
int Solution (int a,int b,int m) //ax≡b mod m //return x
{
int x=0;
int A=a/b;
if(M_I(A,m)==0) x=-1;
else x=M_I(A,m);
return x;
}
int main()
{
//……
return 0;
}
2、实现模指数运算的函数,给定x、y和m,求x的y次方模m
代码
#include<iostream>
#include<cmath>
using namespace std;
enum evenodd{even,odd};
evenodd Y;
//input x、y、m
//return (x^y)mod m
int ModulusIndex(int x,int y,int m)
{
if(y==0) return 1;
int next=ModulusIndex(x,y/2,m);
y%2==1?Y=odd:Y=even; //判断y为偶数还是奇数
if(Y==even) return (next*next)%m;
else return (x*next*next)%m;
}
int main()
{
int x=0,y=0,m=0;
int YorN=0; //again or exit
do
{
cout<<"请先后输入x、y、m:((x^y)mod m )";
cin>>x>>y>>m;
cout<<ModulusIndex(x,y,m);
cout<<"\nagian input 1,exit input 0:";
cin>>YorN;
}while(YorN==1);
return 0;
}
3、设p=23和a=5,使用费尔马小定理计算a^{2020}mod p?
解:
判断23为素数,且5<23,满足费尔马小定理的使用。
由费尔马小定理: 522mod 23 =1, 可以表示为 522=23n+1
52020mod 23=(51998×522)mod 23=(51998×(23n+1))mod 23
=51998mod23
据此,2020%23=18
有 52020mod 23 = 518mod 23
利用上面的模指数函数可得
518mod 23 = 6
4、使用欧拉定理计算 2^{100000} mod 55
解
gcd(2,55)=1,可以使用欧拉定理
Φ(55)=40
2Φ(55)mod 55 =240mod 55 =1
2100000mod 55 =240*2500mod 55 =1
5、手动计算7^{1000}的最后两个数位等于什么?
解
等价于计算71000mod 100
gcd(7,100)=1, 满足欧拉定理使用条件
Φ(100)=40
7Φ(100)mod 100 =740mod 100 =1
显然,最后两位数位等于 01