新征程2.20 数论(一)同余、乘法逆元

前言:

今天开数论了,蒟蒻的我差一点就没就没听懂,由于笔者目前有太多事没干。所以这里长话短说。


首先在学习数论之前,要掌握一些前置知识,例如快速幂,gcd,lcm,模意义等知识。这是基础,不懂的自己去CSDN找资料。


同余

数论中的重要概念。给定一个正整数m,如果二整数α、b)满足m│α-b)(α-b)被m整除),就称整数α、b)对模m同余,记作α≡b)(mod m)。对模m同余是整数的一个等价关系。

显然,有如下事实

(1)若a≡0(mod m),则m|a;

(2)a≡b(mod m)等价于a与b分别用m去除,余数相同。

#include<iostream>
#include<cstdio>

using namespace std;
long long a,b,x,y,z,k;

void work(long long a,long long b)
{
	if(b==0)
	{
		x=1;
		y=0;
		return;
	}
	work(b,a%b);
	k=x;x=y;
	y=k-a/b*y;
	return;
}

int main()
{
    scanf("%lld%lld",&a,&b);
	work(a,b);
	cout<<(x+b)%b;
	return 0;	
}


扩展欧几里得算法

扩展欧几里得算法是欧几里得算法(又叫辗转相除法)的扩展。除了计算a、b两个整数的最大公约数,此算法还能找到整数x、y(其中一个很可能是负数)。通常谈到最大公因子时, 我们都会提到一个非常基本的事实: 给予二整数 a 与 b, 必存在有整数 x 与 y 使得ax + by = gcd(a,b)。有两个数a,b,对它们进行辗转相除法,可得它们的最大公约数——这是众所周知的。然后,收集辗转相除法中产生的式子,倒回去,可以得到ax+by=gcd(a,b)的整数解。


乘法逆元

方法一(80pts)
#include <iostream>
#define int long long

using namespace std;
int n, p, x, y, k;

int GCD(int a, int b) 
{
	return b ? GCD(b ,a%b) : a;
}

void work(int a, int b) 
{
	if (b == 0) 
	{
		x = 1;
		y = 0;
		return;
	}
	
	work(b, a%b);
	k = x;
	x = y;
	y = k - a / b * y;
	return;
}

signed main() 
{
	scanf("%lld%lld", &n, &p);
	
	for(int i = 1; i <= n; i ++) 
	{
		
			work(i, p);
			printf("%lld\n", (x%p+p)%p);
	}
	
	return 0;
}   
方法二(64 pts)
#include<iostream>
#include<cstdio>
#define ll long long

using namespace std;

ll n,p;

ll ksm(ll x,ll y) 
{
	if(y==0) return 1;
	long long t=ksm(x,y/2)%p;
	if(y%2) return (t*t*x)%p;
	else return (t*t)%p;
}

int main() 
{
	scanf("%lld%lld",&n,&p);
	
	for(int i=1;i<=n;i++) printf("%lld\n",ksm(i,p-2));
	
	return 0;
}

方法三不会;

如果你在乘法逆元中仍存疑惑,那么我建议你去这里学习一下,讲的很详细

posted @ 2024-04-03 16:10  deviancez  阅读(124)  评论(0)    收藏  举报