这里写目录标题
- 质数
- 试除法判定质数
- 晒质数
- 埃及筛
- 线性筛
- 约数
- 试除法求约数
- 约数个数与约数之和
- AcWing 870. 约数个数
- AcWing 871. 约数之和
- 欧几里德求最大公因数
质数
埃及筛虽然用的不多,大多使用线性筛,但是埃及筛的思想很重要
试除法判定质数
AcWing 866. 试除法判定质数
bool isPrime(int x)
{
if (x < 2) return false;
for (int i = 2; i <= x / i; i ++ )//不要用开方函数或者i*i小于x。开方函数慢,i*i可能越界
if (x % i == 0)
return false;
return true;
}
AcWing 867. 分解质因数
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
using namespace std;
void get_prime_factor(int x)
{
for (int i = 2; i <= x / i; ++ i)
{
if (x % i == 0)
{
cout << i << " ";
int t = 0;
while (x % i == 0) x /= i, t ++;
cout << t << endl;
}
}
if (x > 1) cout << x << " 1" << endl;
cout << endl;
return ;
}
void solve()
{
int n;
cin >> n;
while (n --)
{
int x;
cin >> x;
get_prime_factor(x);
}
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while (T --) solve();
return 0;
}
晒质数
埃及筛
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
using namespace std;
const int N = 1e6 + 10;//不太记得最多多少个质数了
int primes[N];
bool st[N];
int get_prime(int x)
{
int cnt = 0;
for (int i = 2; i <= x; ++ i)
{
if (st[i]) continue;
primes[cnt ++ ] = i;
for (int j = i + i; j <= x; j += i)//将每个数的倍数筛掉,有倍数的一定是合数
st[j] = true;
}
return cnt;
}
void solve()
{
int x;
cin >> x;
cout << get_prime(x);
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while (T --) solve();
return 0;
}
线性筛
在埃及筛上优化了一下,每个数字只会被筛掉一次,因此是线性的
int get_prime(int x)
{
int cnt = 0;
for (int i = 2; i <= x; ++ i)//第一个循环和埃及筛的意义不一样
{
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; primes[j] <= x / i; ++ j)//不用j < cnt,因为primes[j] <= x / i的时候j一定 >= cnt
{
//prime[j] * i 只会会在pj * i / pj的时候被筛掉
//因为我们保证了pj是其最小质因子
st[primes[j] * i] = true;//每个合数分解到最后都是由一个个质数组成的
if (i % primes[j] == 0) break;//线性筛算法精髓所在,保证primes[j]始终是每个被筛掉的数的最小质因子
}
}
return cnt;
}
约数
试除法求约数
试除法就是枚举
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
using namespace std;
const int N = 1e5 + 10;
int divsors[N];
int cnt;
int get_divsors(int x)
{
memset(divsors, 0, sizeof divsors);
cnt = 0;
for (int i = 1; i <= x / i; ++ i)
{
if (x % i == 0)
{
divsors[cnt ++ ] = i;
if (i != x / i) divsors[cnt ++] = x / i;
}
}
sort(divsors, divsors + cnt);
}
void solve()
{
int n;
cin >> n;
while (n -- )
{
int x;
cin >> x;
get_divsors(x);
for (int i = 0; i < cnt; ++ i)
{
cout << divsors[i] << " ";
}
cout << endl;
}
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while (T --) solve();
return 0;
}
约数个数与约数之和
AcWing 870. 约数个数
重点是以下
约数的意义
计算个数的时候为什么要加1
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10, p = 1e9 + 7;
unordered_map<int, int> divsorts;
void get_divsors(int x)
{
for (int i = 2; i <= x / i; ++ i)
{
while (x % i == 0)
{
divsorts[i] ++;
x /= i;
}
}
if (x > 1) divsorts[x] ++;
}
void solve()
{
int n;
cin >> n;
while (n --)
{
int x;
cin >> x;
get_divsors(x);
}
int res = 1;
for (auto cnt : divsorts) res = (LL)res * (cnt.second + 1) % p;
cout << res;
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while (T --) solve();
return 0;
}
AcWing 871. 约数之和
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10, mod = 1e9 + 7;
unordered_map<int, int> divsorts;
void get_divsors(int x)
{
for (int i = 2; i <= x / i; ++ i)
{
while (x % i == 0)
{
divsorts[i] ++;
x /= i;
}
}
if (x > 1) divsorts[x] ++ ;
}
void solve()
{
int n;
cin >> n;
while (n --)
{
int x;
cin >> x;
get_divsors(x);
}
LL res = 1;
for (auto divsort : divsorts)
{
LL t = 1;
int a = divsort.first, b = divsort.second;
while (b -- ) t = (t * a + 1) % mod;
res = res * t % mod;
}
cout << res;
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while (T --) solve();
return 0;
}
欧几里德求最大公因数
求最大公因数还有一个算法就是根相减损术
A:a,B:b,D:a - m*b(a % b)
递归到最后就是 x和0的最大公约数就是x
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <vector>
#include <queue>
#include <map>
#include <unordered_map>
using namespace std;
int get_max_divsort(int a, int b)
{
if (b != 0) return get_max_divsort(b, a % b);
else return a;
}
void solve()
{
int n;
cin >> n;
while (n --)
{
int a, b;
cin >> a >> b;
int res = get_max_divsort(a, b);
cout << res << endl;
}
}
int32_t main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
//cin >> T;
while (T --) solve();
return 0;
}