简单数论(更新中)

需要掌握
1.快速幂,快速乘。
2.扩展欧几里得求解方程,求同余式,求逆元。
3.之后再总结

将一个大质数分解为两个大质数的乘积,直接用暴力求解。
for (long long i = 2; i <= (long long)sqrt(1.0 * n); ++i){
	if (n % i == 0){
		p = i;
		q = n / p;
		cout << p << " " << q << endl;
	}
} 

在这里插入图片描述
注意:
(a/b) mod m的求法。

//快速幂
long long f(int m, int n){
	int ans = 1;
	while (n){
		if (n & 1){
			ans *= m;  //ans = ans * m % ...如果要求对结果取模可在这里取模,如果ans*m发生越界,就得使用快速乘来替代。
		}
		m *= m;
		n >>= 1;
	}
	return ans;
}

注意:if(n&1) 这个条件
在这里插入图片描述

long long fast_cheng(long long a, long long b, long long n){ //求(a*b) mod n 
	long long ans = 0;
	while (b){
		if (b & 1) ans = (ans + a) % n;
		a = (a * 2) % n;
		b >>= 1;
	}
	return ans;
}

在这里插入图片描述
注意:x1 和 y1 的递归式要记牢!!!

#include <bits/stdc++.h>
using namespace std;
//拓展欧几里求4x+6y=18	
int exgcd(int a, int b, int &x, int &y){
	if (b == 0) {
		x = 1; 
		y = 0;
		return a;
	}
	int gcd = exgcd(b, a % b, x, y);
	int tmp = x;
	x = y;
	y = tmp - a / b * y; //这个a b是当前层的a b 
	return gcd;
}
int main(){
	int x1 = 0, y1 = 0;
	int gcd_ = exgcd(4, 6, x1, y1);
	cout << x1 * 18 / gcd_ << endl;
	cout << y1 * 18 / gcd_ << endl;
	return 0;
}

注意:
y = tmp - a / b * y;别把tmp写成了x
在这里插入图片描述在这里插入图片描述

注意:
1.a与m必须互质才能求逆元,比如不能求4x+6y=1
2. 逆元都是正整数,所以用扩展欧几里得求逆元后得到的x需要处理一下,
((x%m)+m)%m才是逆元
3.逆元的含义:满足的最小正整数值。
4. 费马引理用快速幂求逆元的条件是m为素数才可以!
5. 用快速幂求逆元可能会超出long long范围,所以最好用扩展欧几里得求!

int main(){
	int x, y;
	//求 ax = 1(mod m) 也就是a的逆元 2x = 1(mod 9)
	int gcd = exgcd(2, 9, x, y);
	cout << "2mod9的逆元" << (x % 9 + 9) % 9; !!!
	return 0;
} 
#include <bits/stdc++.h>
using namespace std;

int di[100];
int zhi[100]; 
int cnt = 0;
//唯一分解定理
void f(int n){
	memset(zhi, 0, sizeof(zhi));
	cnt = 0;
	int tmp = n;
	for (int i = 2; i <= (int)sqrt(1.0 * n); ++i){
		if (tmp == 1) break;
		if (tmp % i == 0){
			di[++cnt] = i;
			while (tmp % i == 0){
				zhi[cnt]++;
				tmp /= i;
			}
		}

	}
	if (tmp > 1) {
		di[++cnt] = tmp; zhi[cnt]++;
	}
} 
int main(){
	
	f(100);
	for (int i = 1; i <= cnt; ++i){
		if (i != 1) cout << "*";
		cout << di[i];
		if (zhi[i] > 1) {
			cout << "^";
			cout << zhi[i];
		}
	}
	cout << endl;
	
	return 0;
}

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
 
int isprime[101];
int prime[101];
int cnt = 0;
//判断是否是素数
int judeg(int n){
	if (n <= 1) returan false;
	for (int i = 2; i <= (int)sqrt(1.0 * n); ++i){
		if (n % i == 0) return false;
	}
	return true;
}
//埃式筛
void f1(int n){
	cnt = 0;
	memset(isprime, 0, sizeof(isprime));
	for (int i = 2; i <= n; ++i){
		if (!isprime[i]){
			prime[cnt++] = i;
			for (int j = i * i; j <= n; j += i){ //从i*i开始
				isprime[j] = 1;
			} 
		}
	}
}
//线性筛 
void f2(int n){
	cnt = 0;
	memset(isprime, 0, sizeof(isprime));
	for (int i = 2; i <= n; ++i){
		if (!isprime[i]) prime[++cnt] = i;
		for (int j = 1; j <= cnt; ++j){
			if (prime[j] * i > n) break;
			isprime[prime[j] * i] = 1;
			if (i % prime[j] == 0) break; 
		}
	}
}
int main(){
	f1(100);
	cout << cnt << endl;
	for (int i = 0; i < cnt; ++i){
		cout << prime[i] << " ";
	}
	cnt = 0;
	f2(100);
	cout << endl << cnt << endl;
	for (int i = 0; i < cnt; ++i){
		cout << prime[i] << " ";
	}
	
	return 0;
}

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;

//求某个数的欧拉函数 
int f(int n){
	int ans = n;
	int tmp = n;
	for (int i = 2; i <= (int)sqrt(1.0 * n); ++i){
		if (tmp == 1) break;
		if (tmp % i == 0){
			ans = ans * (i - 1) / (i);  
			while (tmp % i == 0) tmp /= i; //比如8的欧拉函数=8*(1/2)而没有(3/4) 
		}
	}
	if (tmp > 1)  ans = ans / (tmp) * (tmp - 1);
	return ans;
} 
int main(){
	
	cout << f(8);
	return 0;
}

//求某个范围的欧拉函数,没有自己写,先粘贴上来吧
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值