质数判定
适用场景,有10^5个测试点,并且每个测试点需要判断一个>10 ^6的数是否是质数,如果单纯使用根号n的方法是会超时的,所以需要更快的质数判定法
试除法判定质数
bool isPrime(int x)
{
if (x < 2) return false;
for (int i = 2; i <= x / i; i ++) //只需要枚举较小的因子即可,这里需要等于号(平方的情况)
{
if (x % i == 0) return false;
}
return true;
}
试除法分解质因数
void divide(int x)
{
for (int i = 2; i <= x / i; i ++) //遍历x较小的质因数
{
if (x % i == 0)
{
int c = 0;
while (x % i == 0)
{
x /= i;
c ++;
}
cout << i << " " << c << endl;
}
}
if (x > 1) cout << x << " " << 1 << endl; //>sqrt(x)的质因数最多只有可能有一个
}
朴素法筛质数
for (int i = 2; i <= n; i ++)
{
if (!st[i]) res ++; //质数个数加一
for (int j = i + i; j <= n; j += i) st[j] = true; //删去每一个数的倍数
}
埃式筛质数
for (int i = 2; i <= n; i ++)
{
if (!st[i])
{
res ++; //质数个数加一
for (int j = i + i; j <= n; j += i) st[j] = true; //删去质数的倍数
}
}
线性法筛质数
for (int i = 2; i <= n; i ++)
{
if (!st[i])
{
res ++;//质数个数加一
p[cnt ++] = i; //从小到大记录个数
}
for (int j = 0; p[j] <= n / i; j ++)
{
st[p[j] * i] = true;
if (i % p[j] == 0) break;
}
}
试除法求约数
vector <int> res;
for (int i = 1; i <= x / i; i ++)
{
if (x % i == 0)
{
res.push_back(i);
if (x / i != i) res.push_back(x / i);
}
}
公式法求约数个数
long long res = 1;
unordered_map <int, int> m;
while (n --)
{
int x;
cin >> x;
//分解质因数,记录对应指数
for (int i = 2; i <= x / i; i ++)
{
while (x % i == 0)
{
x /= i;
m[i] ++;
}
}
if (x > 1) m[x] ++;
}
//对每一个指数加一求乘积
for (auto x : m)
{
res = res * (x.second + 1) % mod;
}
公式法求约数和
long long res = 1;
unordered_map <int, int> m;
//分解质因数,记录其指数
while (n --)
{
int x;
cin >> x;
for (int i = 2; i <= x / i; i ++)
{
while (x % i == 0)
{
x /= i;
m[i] ++;
}
}
if (x > 1) m[x] ++;
}
//求多项式并求乘积
for (auto x : m)
{
int a = x.first, b = x.second;
long long t = 1;
while (b --) t = (t * a + 1) % mod;
res = res * t % mod;
}
辗转相除法求最大公约数
//(a, b) = (b, a % b) 如果b大于0,返回gcd(b, a % b), 否则(0, a) 返回a
int gcd(int a, int b)
{
return b ? gcd(b, a % b) : a;
}