数论相关学习

目录

同余

gcd,lcm

唯一分解定理

素数三大筛

朴素素数筛

埃式筛

欧拉筛

快速幂&龟速乘

广义幂

龟速乘


同余

使用条件:当数据很大时

(a+b) mod n =( (a mod n) + (b mod n) ) mod n

(a -b) mod n =( (a mod n) - (b mod n) ) mod n

(a*b) mod n =( (a mod n) * (b mod n) ) mod n

gcd,lcm

前置知识:

1.如果一个数为0,则最大公约数就是另一个不为0的数

2.lcm=(a*b)/gcd(a,b)

所以我们就来了解下gcd求法就好,lcm可以根据gcd直接求得

1.更相减损法

两个正整数a,b(a>b),他们最大公约数就是a-b的差值c和较小数b的最大公约数

 递归写法

int gcd_1(int a,int b)
{
	if(a==0) 
		return b;
	if(b==0)
		return a;
	if(a==b)
		return a;
	if(a>b)
		return gcd(a-b,b);
	if(a<b)
		return gcd(b-a,a);
}

循环写法

int gcd_2(int a,int b)
{
	if(a==0)
		return b;
	if(b==0)
		return a;
	while(a!=b)
	{
		if(a>b)
			a-=b;
		else 
		{
			int t=a;
			a=b-a;
			b=t;
		}
	}
	return a;
}

2.辗转相除法

两个正整数a,b(a>b),他们最大公约数就是a%b的值c和较小数b的最大公约数

循环写法

int gcd_3(int a,int b)
{
	while(b>0)
	{
		int t=a%b;
		a=b;
		b=t;
	}
	return a;
}

递归写法

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

唯一分解定理

每个大于1的自然数均可写为质数的积,而且这些因子按大小排列后,写法仅有一种

例如:12=2 * 2 * 3

while(i*i<=n)
{
	i++;
	while(n%i==0)
	{
		printf("%d ",i);
		n/=i;
	}
}
if(n!=1)
	printf("%d",n);

素数三大筛

朴素素数筛
{
	if(x==0||x==1) 
	return false;
	for(int i=2;i*i<=x;i++)
	{
		if(x%i==0)
		return false;
	}
	return true;
}
埃式筛

对已知的素数进行加倍操作,那么大于2的整数倍数都是合数

bool vis[N]={true,true};//0和1不是素数 
int main()
{
	for(int i=2;i*i<=N;i++)
	{
		if(!vis[i])
		{
			for(int j=i*2;j<=N;j+=i)
				vis[j]=true;
		}
	}
}
欧拉筛

和埃氏筛类似,但是埃氏筛中重复筛选过一些元素,而欧拉筛避免了重复

任何合数都能分解成多个素数的积,所以,任何合数都有一个最小质因子,我们通过这个最小质因子就可以知道筛选什么时候结束。

int prime[N];
bool vis[N];

void get_prime()
{
	memset(vis,true,sizeof vis);//初始化数组 
	memset(prime,0,sizeof prime);
	vis[0]=false;
	vis[1]=false;
	for(int i=2;i<=N;i++)
	{
		if(vis[i])
		{
			prime[++prime[0]]=i;
		}
		for(int j=1;j<=prime[0]&&i*prime[j]<=N;j++)
		{
			vis[i*prime[j]]=false;
			if(i%prime[j]==0)//避免重复筛选 
				break;
		}
	}	
}

快速幂&龟速乘

给出三个数a,b,c,求pow(a,b)%c(当b很大时),结合位运算进行解决

ll ksm(ll a,ll b,ll c)
{
	ll res=1;
	while(b>0)
	{
		if(b&1)
		{
			res=(res*a)%c;
		}
		a=(a*a)%c;
		b=b>>1;
	}
	return res;
}
广义幂

已知数列a1,a2,a3....an和c

求(a1 * a2 * a3 * .....an)%c

计算a关于#运算的n次幂的快速幂

res=x;
temp=y;
while(n)
{
	if(n&1)
	{
		res=res#temp;
	}
	temp=temp#temp;
	n=n>>1;
}
龟速乘

计算两个大整数(long long 范围内)a,b的乘积并取模c

ll gsc(ll a,ll b,ll c)
{
	ll res=0;
	a%=c;
	b%=c;
	while(b>0)
	{
		if(b&1)
		{
			res=(res+a)%c;
		}
		a=(a%c+a%c)%c;
		b=b>>1;
	}
	return res%c;
}

更多的后面慢慢补充

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值