蓝桥杯中常用的数学算法
Posted JunMain
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了蓝桥杯中常用的数学算法相关的知识,希望对你有一定的参考价值。
文章目录
算数基本定义
任何一个合数都可以写成,若干个质数相乘
n = q 1 B 1 ∗ q 2 B 2 ∗ ⋅ ⋅ ⋅ ∗ q n B n n = q_1^B_1 * q_2^B_2 * ···*q_n^B_n n=q1B1∗q2B2∗⋅⋅⋅∗qnBn (n是一个合数, q i q_i qi是质数)
因此只要是一个合数我们就可以分解质因数,并且 n最多只有一个大于 n \\sqrtn n的质因子
分解质因数 O ( n ) O(\\sqrtn) O(n)
#include<bits/stdc++.h>
using namespace std;
int main()
int n;
cin >> n;
for (int i = 2; i <= n / i; i ++)
if (n % i == 0)
int s = 0;
while (n % i == 0)
n /= i;
s ++;
cout << i << " " << s << endl;
if (n > 1) cout << n << " " << 1 << endl;
return 0;
质数
质数是除了1和本身外不能被其他数字整除的数字
试除法 O ( n ) O(\\sqrtn) O(n)
#include<bits/stdc++.h>
using namespace std;
bool is_prime(int n)
if (n < 2) return false;
for (int i = 2; i <= n / i; i ++)
if (n % i == 0 ) return false;
return true;
int main()
int n;
cin >> n;
cout << is_prime(n);
return 0;
朴素筛法求质数 ( n l o g n ) (nlog_n) (nlogn)
利用筛法可以求出1 - n中的所有素数, 可以进行预处理
基本思路:把所有数字的倍数删掉,剩下的数字就是质数
#include<bits/stdc++.h>
using namespace std;
const int N = 1000010;
bool st[N];
int prime[N], cnt;
int main()
int n;
cin >> n;
for (int i = 2; i <= n; i ++)
if (!st[i])
prime[cnt ++] = i;
for (int j = i; j <= n; j += i) st[i] = true;
return 0;
埃式筛法 O ( n l o g l o g n ) O(nlog_log_n) O(nloglogn) ~ O ( n ) O(n) O(n)
一个埃及人发明的筛法
根据算数基本定理:任何一个合数都是有若干个质数相乘,
我们可以优化上面的朴素筛法,每次去掉质数的倍数, 最后剩下的一定是素数
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
bool st[N];
int prime[N], cnt;
int main()
int n;
cin >> n;
for (int i = 2; i <= n; i ++)
if (!st[i])
prime[cnt ++] = i;
for (int j = i; j <= n; j += i) st = true;
return 0;
线性筛法 O ( n ) O(n) O(n)
线性筛法的核心原理: 一个合数n只会被它的最小质因子筛掉
#include<bits/stdc++.h>
using namespace std;
const int N = 1000010;
bool st[N];
int prime[N], cnt;
int main()
int n;
cin >> n;
for (int i = 2; i <= n; i ++)
if (!st[i]) prime[cnt ++] = i;
for (int j = 0; prime[j] <= n / i; j ++) //从小到大枚举所有质数
st[prime[j] * i] = true; //i%p[j]!=0 p[j]一定小于i的所有质因子一定是 p[j]*i 的最小质因子
if (i % prime[j] == 0) break; //i%p[j]==0 p[j]此时一定是i的最小质因子
return 0;
约数
试除法求约数 O ( n ) O(\\sqrtn) O(n)
求 n n n 的约数
#include<bits/stdc++.h>
using namespace std;
vector<int> res;
int main()
int n;
cin >> n;
for (int i = 1; i <= n / i; i ++)
if (n % i == 0)
res.push_back(i);
if (i != n / i ) res.push_back(n / i); //特判 平方
sort(res.begin(), res.end());
return 0;
求约数个数 O ( n ) O(\\sqrtn) O(n)
算数基本定理: n = q 1 B 1 ∗ q 2 B 2 ∗ ⋅ ⋅ ⋅ ∗ q n B n n = q_1^B_1 * q_2^B_2 * ···*q_n^B_n n=q1B1∗q2B2∗⋅⋅⋅∗qnBn (n是一个合数, q i q_i qi是质数)
公式: n的约数个数 = ( B 1 + 1 ) ∗ ( B 2 + 1 ) ∗ ⋅ ⋅ ⋅ ∗ ( B n + 1 ) (B_1 + 1)*(B_2 + 1)*···*(B_n + 1) (B1+1)∗(B2+1)∗⋅⋅⋅∗(Bn+1)
int 范围内约数的个数最多在1500个左右
#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int> mp;
int ans = 1;
int main()
int n;
cin >> n;
for (int i = 2; i <= n / i; i ++)
if (n % i == 0)
while (n % i == 0)
mp[i] ++;
n /= i;
if (n > 1) mp[n] ++;
for (auto m : mp)
ans *= (m.second + 1);
cout << ans;
return 0;
求约数之和
算数基本定理: n = q 1 B 1 ∗ q 2 B 2 ∗ ⋅ ⋅ ⋅ ∗ q n B n n = q_1^B_1 * q_2^B_2 * ···*q_n^B_n n=q1B1∗q2B2∗⋅⋅⋅∗qnB尽快收藏蓝桥杯常用算法模板