需要掌握
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;
}
//求某个范围的欧拉函数,没有自己写,先粘贴上来吧