numberTheory.hpp
is assume to be a prime number, and for arbitrary module.
please use
g++ -o main main.cpp -std=c++17 -O2
to complier examples below.
Prime
It is a singleton which has member isP, p, pi
, and method: primePi
and nthPrime
where
The key point is: if , then
See cnblog or origin paper package for detail.
Constraints
- primePi(n):
- nthPrime(n):
Complexity
- primePi(n):
- nthPrime(n):
Example
#include <bits/stdc++.h>
using LL = long long;
#include "cpplib/math/numberTheory.hpp"
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
auto start = std::clock();
auto& prime = Prime::Instance();
std::cerr << "Init time used: " << (std::clock() - start) / 1000 << "ms" << std::endl;
LL n = prime.primePi(123456789012LL);
std::cout << n << '\n';
LL x = prime.nthPrime(n);
std::cout << x << '\n';
// It must the same as n
std::cout << prime.primePi(x) << '\n';
std::cerr << "Total time used: " << (std::clock() - start) / 1000 << "ms" << std::endl;
return 0;
}
Euler and Mobius
Euler's Totient function and Mobius function. The have many in common.
The key points are:
and then numberTheoryBlock
tech is used to give a implement.
Example
#include <bits/stdc++.h>
#define clog(x) std::clog << (#x) << " is " << (x) << '\n';
using LL = long long;
#include "cpplib/math/numberTheory.hpp"
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
auto start = std::clock();
auto& euler = Euler::Instance();
auto& Mobius = Mobius::Instance();
std::cerr << "Init time used: " << (std::clock() - start) / 1000 << "ms" << '\n';
int n = 1e9 + 7;
clog(euler.getPhi(n));
clog(euler.getSumPhi(n));
clog(Mobius.getMu(n));
clog(Mobius.getSumMu(n));
clog(Mobius.getAbsSum(n));
std::cerr << "Total time used: " << (std::clock() - start) / 1000 << "ms" << '\n';
return 0;
}
npf
std::pair<std::vector<int>, std::vector<int>> npf(int N)
// auto [a, b] = npf(N)
init numbers of (multi) prime factors less than
Complexity
Example
- 5
factor and Factor
std::vector<int> factor(int n, const std::vector<int>& sp)
std::vector<std::pair<int, int>> Factor(int n, const std::vector<int>& sp)
factor into prime number
Complexity
Example
primitiveRoot
int primitiveRoot(int n, const std::vector<int>& sp)
return smallest primitive root or 0 if not exist.
have primitive root if and only if where is prime number.
Complexity
Example
primitiveRootAll
std::vector<int> primitiveRootAll(int n, const std::vector<int>& sp)
return list of all primitive roots or empty if not exist
Complexity
Example
PollardRho
Pollard-rho algorithm is a probabilistic method for big number decomposition, which is based on big prime test probabilistic method: Miller-Rabin
bool PollardRho::rabin(LL n)
LL PollardRho::spf(LL n)
LL PollardRho::gpf(LL n, LL mxf = 1)
Complexity
babyStepGiantStep
find smallest non-negative s.t. , or
Constraints
- is prime
Complexity
sqrtModp
int sqrtModp(int a, int p)
Constraints
- is prime
Complexity
lcmPair
std::vector<std::tuple<int, int, int>> lcmPair(int n)
return all pair with
Complexity
DirichletProduct
give two function, , we define Dirichlet Product of as defined as
- , then is call Mobius transform,
- , then is call Mobius inverse transform, where is mobius function
Complexity
- DirichletProduct:
- Mobius transform:
- Mobius inverse transform:
DirichletProduct Test
// docs/test/math/DirichletTest1.cpp
#include <bits/stdc++.h>
using LL = long long;
#include "../../cpplib/math/numberTheory.hpp"
using UL = unsigned long long;
std::mt19937_64 rnd64(std::chrono::steady_clock::now().time_since_epoch().count());
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
int n = 1e5;
std::vector<UL> a(n + 1), e(n + 1, 1), mu(n + 1);
e[0] = 0;
mu[1] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = i * 2; j <= n; j += i) {
mu[j] -= mu[i];
}
}
for (int i = 1; i <= n; ++i) a[i] = rnd64();
auto b = a;
auto c = DirichletProduct(a, e, n);
mobiousTran(a, n);
for (int i = 0; i <= n; ++i) assert(a[i] == c[i]);
c = DirichletProduct(c, mu, n);
mobiousTranInv(a, n);
for (int i = 0; i <= n; ++i) assert(a[i] == c[i]);
for (int i = 0; i <= n; ++i) assert(a[i] == b[i]);
c = DirichletRevProduct(a, e, n);
mobiousRevTran(a, n);
for (int i = 0; i <= n; ++i) assert(a[i] == c[i]);
c = DirichletRevProduct(c, mu, n);
mobiousRevTranInv(a, n);
for (int i = 0; i <= n; ++i) assert(a[i] == c[i]);
for (int i = 0; i <= n; ++i) assert(a[i] == b[i]);
return 0;
}