Fundamentals of number theory
to be divisible by
For two integers \ (a \, \ B (a \ NEQ 0) \), if \ (\ exists k\in Z \) makes \ (ak=b \), it is called \ (a \) divisible \ (B \) and recorded as \ (a|b \)
Counting
P1226 [template] fast power | remainder operation
Fast power for fast calculation \ (x^y\ \%\ mod \)
The idea of calculation is: take the decimal \ (y \) as binary, and then count the answers through some operations under binary
The following cases have been defaulted to binary
Process:
For the calculation of \ (x^y \), the \ (Y \) is expressed as binary, such as: \ (105 {(10)} = 1101001 {(2)} \)
So \ (x^y = x^{105} = x^{2^6+2^5+2^3+2^0}=x^{2^6}x^{2^5}x^{2^3}x^{2^0} \)
Use the variable \ (ans \) to count the answers
x | ans |
---|---|
\(x\) | \(x^{2^0}\) |
\(x^2\) | \(x^{2^0}\) |
\(x^4\) | \(x^{2^0}\) |
\(x^8\) | \(x^{2^3}x^{2^0}\) |
\(x^{16}\) | \(x^{2^3}x^{2^0}\) |
\(x^{32}\) | \(x^{2^5}x^{2^3}x^{2^0}\) |
\(x^{64}\) | \(x^{2^6}x^{2^5}x^{2^3}x^{2^0}\) |
int ksm(int x, int y, int mod) { int ans = 1; for( ; y; y >>= 1, (x *= x) %= mod) if(y & 1) (ans *= x) %= mod; return ans; }
Note: the expression of \ ((a *= b) \%= mod \) is equivalent to \ (a = (a * b) \%mod \)
Time complexity: \ (O(log\ y) \)
gcd
The maximum common divisor of two numbers \ (a \), \ (B \)
Pei Shu theorem
For any \ (x \, \ y \), all \ (\ exists \ a,b \) satisfy \ (ax+by=gcd(x,y) \)
application
Used to do questions
Can be used to prove strange things and push formulas
In information, the common routine for this thing is enumeration \ (gcd \)
For example, give you T groups of data and find \ (\ sum {I = 1} ^ n \ sum {J = 1} ^ m GCD (I, J) \)
One step is the standard enumeration \ (gcd \)
\(\displaystyle \ \sum_{i=1}^n \sum_{j=1}^m gcd(i,j)\)
\(=\displaystyle \sum_{i=1}^n \sum_{j=1}^m \sum_{d|i,j}d[gcd(\frac id,\frac jd)==1]\)
\(\mathcal{Code}:\)
int Gcd(int x, int y) { return y ? Gcd(y, x % y) : x; }
extended euclidean algorithm
P1082 [NOIP2012 improvement group] congruence equation
Algorithm description
Integer solution for solving the equation \ (ax+by = gcd(a, b) \) about \ (x,y \)
The necessary condition for the solution of equation \ (ax + by = m \) is \ (m\ mod\ gcd(a, b) = 0 \)
prove:
Easily obtained from known conditions: \ (a\ mod\ gcd(a, b) = 0,b\ mod\ gcd(a, b) = 0 \)
Then \ ((ax + by)\ mod\ gcd(a, b) = 0 \)
That is \ (m\ mod\ gcd(a, b) = 0 \)
Pre knowledge: Euclidean algorithm (rolling Division)
Euclidean algorithm is used to solve the greatest common factor of two numbers
int Gcd(int x, int y) { return y ? Gcd(y, x % y) : x; }
If we already know the following formula
It can be concluded that
Then there
When \ (b = 0 \) \ (ax = a \)
At this time \ (y \) is better to take \ (0 \), because during backtracking, \ (y \) increases rapidly and the value is easy to cross the boundary
int Ex_gcd(int a, int b, int &x, int &y) { if(b == 0) return x = 1, y = 0, a; int ans = Ex_gcd(b, a % b, x, y); int tmp = x; x = y; y = tmp - a / b * y; return ans; }
In this way, a set of solutions of equation \ (ax+by=gcd(a, b) \) can be found
To solve a set of solutions in which \ (x \) is the smallest positive integer, it can be derived from the following formula
Then \ (x = (x \% b + b) \% b \)
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 1e6 + 5; typedef long long LL; int read() { int x = 0, f = 1; char ch; while(! isdigit(ch = getchar())) (ch == '-') && (f = -f); for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 3) + (x << 1) + (ch ^ 48)); return x * f; } template <class T> T Max(T a, T b) { return a > b ? a : b; } template <class T> T Min(T a, T b) { return a < b ? a : b; } int Ex_gcd(int a, int b, int &x, int &y) { if(b == 0) return x = 1, y = 0, a; int ans = Ex_gcd(b, a % b, x, y); int tmp = x; x = y; y = tmp - a / b * y; return ans; } int main() { int a = read(), b = read(), x, y; Ex_gcd(a, b, x, y); x = (x % b + b) % b; printf("%d\n", x); return 0; }
Example: P1516 frog date
lcm
There's really nothing to say about this
\(lcm \) this thing is rejected because it has no nature in number theory
Usually convert \ (lcm \) to \ (gcd \): \ (lcm(i,j)=\frac {i*j}{gcd(i,j)} \)
Note that this property is valid only when there are two numbers, but not necessarily in other cases, such as
\(\frac {1*2*3*4*5}{gcd(1,2,3,4,5)} = 1*2*3*4*5 \neq lcm(1,2,3,4,5)\)
Example: P1891 crazy LCM
congruence
For two integers \ (a \, \ b \), if \ (\ exists \ p \in prime \) makes \ (a\%p == b \% p \), it is said that \ (a \) and \ (b \) are congruent in the sense of module \ (p \)
If represented by a symbol, it is \ (a \equiv b \ (mod \ p) \)
nature
Symmetry: $a \equiv b \ (mod \ p) \ \Rightarrow \ b \equiv a \ (mod \ p)$
Multiplicity: if \ (a \ equiv B \ (MOD \ P) \, \ C \ equiv D \ (MOD \ P) \), then \ (ac \equiv bd \ (mod \ p) \)
application
The information is basic and has no application. It is mainly used in the proof and expression of theorems
For the congruence \ (a \equiv b \ (mod \ p) \), it can be converted to \ (a x+km=b \) and exgcd can be applied
In particular, a solution to the congruence \ (a \equiv 1 \ (mod \ p) \) is the inverse of \ (a \) in the sense of module \ (p \)
Inverse element
For integers \ (a, p \), if \ (\ exists \ a^{-1} \) satisfies \ (a*a^{-1} \ \equiv \ 1(mod \ p) \), it is said that \ (a^{-1} \) is the inverse of \ (a \) in the sense of module \ (p \)
It is mainly used for division module problem
Because division is not closed to modular operation, inverse element arises at the historic moment
There are mainly two methods to find the inverse element, one is Fermat's small theorem, the other is \ (EX gcd \), and the third is linear
Only linear codes are listed
\(\mathcal{Code}:\)
inv[1] = 1; for(int i = 2; i <= n; ++ i) inv[i] = ((p - p/i) * inv[p%i]) % p;
Example: P3811 multiplicative inverse,P5431 multiplicative inverse 2
Eratoseni sieve method
Complexity $\ theta (n logn)$
Therefore, it is recommended to use Euler sieve \ (\ Theta(n) \)
Let's talk about the principle here
For a number \ (a \), then \ (k*a \ (k \in N ^ *) \) will not enter the prime table in the subsequent cycle, so mark them
The complexity is not as good as that of Euler sieve because the Ehrlich sieve will repeat the sieve for some numbers
\(\mathcal{Code}:\)
void calc(){ for(int i = 2; i <= n; ++ i) { if(! vis[i]) prime[++ cnt] = i; for(int j = 1; j <= cnt; ++ j) { if(i * prime[j] <= n) vis[i * prime[j]] = 1; } } }
Example: P3383 linear sieve prime
Du Jiao sieve
For a product function \ (f \), we require \ (\ displaystyle \ sum {I = 1} ^ NF (I) \)
\(\mathcal{Ans}\):
Let \ (S(n)=\displaystyle\sum_{i=1}^n f(i) \), \ (h=g*f\) (h, G are any integral function)
Then \ (\ displaystyle \ sum \ limits {I = 1} ^ {n} (f * g) (I) \)
\(\begin{aligned} &= \sum\limits_{i=1}^{n} \sum \limits _{d|i} g(d)f(\frac{i}{d}) \\ &= \sum \limits _{d=1}^{n} g(d)\sum\limits _{i=1}^{\lfloor \frac{n}{d}\rfloor } f(i) \\ &= \sum \limits _{d=1}^{n} g(d) S(\lfloor \frac{n}{d} \rfloor) \end{aligned}\)
Also \ (\ displaystyle g (1) s (n) = \ sum {d = 1} ^ ng (d) s (\ lfloor \ frac nd \ rfloor) - \ sum {d = 2} ^ ng (d) s (\ lfloor \ frac nd \ rfloor) \)
Then \ (\ displaystyle g (1) s (n) = \ sum \ limits {I = 1} ^ {n} (f * g) (I) - \ sum {d = 2} ^ ng (d) s (\ lfloor \ frac nd \ rfloor) \)
Preprocess \ (\ & \) number theory blocks
Example: P4213 Du Jiao sieve
#include <iostream> #include <cstdio> #include <map> using namespace std; const int N = 6e6 + 5; typedef long long LL; bool vis[N]; int t, cnt, mu[N], phi[N], prime[N], sum1[N]; LL n, sum2[N]; map<int, int> m1; map<LL, LL> m2; inline void prim(int x) { mu[1] = phi[1] = 1; for(int i = 2; i <= x; i ++) { if(vis[i] == 0) { prime[++ cnt] = i; mu[i] = -1, phi[i] = i - 1; } for(int j = 1; j <= cnt && i * prime[j] <= x; j ++) { vis[i * prime[j]] = 1; if(i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j]; break; } else mu[i * prime[j]] = - mu[i], phi[i * prime[j]] = phi[i] * (prime[j] - 1); } } for(int i = 1; i <= x; i ++) sum1[i] = sum1[i-1] + mu[i], sum2[i] = sum2[i-1] + phi[i]; } int djsmu(int x) { if(x <= 6e6) return sum1[x]; if(m1[x]) return m1[x]; int ans = 1; for(int l = 2, r; l <= x; l = r + 1) { r = x/(x/l); ans -= (r - l + 1) * djsmu(x/l); } return m1[x] = ans; } LL djsphi(LL x) { if(x <= 6e6) return sum2[x]; if(m2[x]) return m2[x]; LL ans = x * (x + 1) / 2; for(int l = 2, r; l <= x; l = r + 1) { r = x/(x/l); ans -= (r - l + 1) * djsphi(x/l); } return m2[x] = ans; } int main() { scanf("%d", &t); prim(6000000); while(t --> 0) { scanf("%lld", &n); printf("%lld %d\n", djsphi(n), djsmu(n)); } return 0; }
Lagrange interpolation
Sun Tzu theorem
If \ (m_1,m_2,\cdots,m_n \) is a positive integer with two coprime, \ (M=\prod_{i=1}^n{m_i} \), \ (m_i = m / m_i \), \ (t_i \) is a solution of the linear congruence equation \ (M_it_i\equiv 1 \ (mod \ m_i) \)
For any n integers \ (a_1,a_2,\cdots,a_n \), the Congruence Equations: \ (\ begin{cases}x ≡ a_1(mod\ m_1)\x ≡ a_2(mod\ m_2)\ \cdots \cdots\x ≡ a_n(mod\ m_n)\end{cases} \) have integer solutions
The solution of the system of equations is \ (x = \ sum {I = 1} ^ n M_it_i a_i \), and has a unique solution in the sense of \ (\% \ M \).
prove
Because \ (M_i=M/m_i \) is a multiple of all modules except \ (m_i \), so \ (\ forall \ K \ not = I \, \ m_it_ia_i \ equiv 0 \ (MOD \ m_k) \)
Because \ (M_it_ia_i\equiv a_i\ (mod \ m_i) \)
So \ (x=\sum_{i=1}^n M_it_i a_i \)
conclusion
\(CRT \) gives a special solution of a system of Linear Congruence Equations with two coprime modules. The general solution of the equations can be expressed as \ (x+kM\ (k\in Z) \). Some problems require us to find the minimum nonnegative integer solution. We only need to modulo \ (x \) to \ (M \) and let x fall within \ ([1,M) \).
text
For a polynomial \ (f(x) \), its image passes through \ (n \) points \ ((x_i,y_i) \) in the coordinate system
We consider the "Sun Tzu theorem" for this polynomial:
Construct \ (n \) polynomials \ (g_i(n) \). For the \ (I \) th polynomial, for \ (\ forall k\not= i, g_i(x_k)=0 \), and \ (g_i(x_i)=1 \), that is \ (g_i(x_i)*y_i=y_i \)
Then \ (g_i(x)=\frac{(x-x_1)(x-x_2)\cdots(x-x_{i-1})(x-x_{i+1})\cdots(x-x_n)}{(x_i-x_1)(x_i-x_2)\cdots(x_i-x_{i-1})(x_i-x_{i+1})\cdots(x_i-x_n)} \)
So \ (\ displaystyle f(x)=\sum_{i=1}^n g_i(x)*y_i \)
\(\mathcal{Code}\):
#include <iostream> #include <cstdio> using namespace std; typedef long long LL; const LL N = 2e3 + 5, mod = 998244353; LL n, k, ans, x[N], y[N]; LL ksm(LL a, LL b) { int res = 1; for( ; b ;a = a * a % mod, b >>= 1) { if(b & 1) res = res * a % mod; } return res; } LL Lagrange(LL k) { LL ans = 0; for(int i = 1;i <= n;i ++) { LL res = 1; for(int j = 1;j <= n;j ++) { if(i == j) continue; res = (res * ((x[i] + mod - x[j])%mod)) % mod; } res = ksm(res, mod - 2); for(int j = 1;j <= n;j ++) { if(i == j) continue; res = (res * ((k + mod - x[j])%mod)) % mod; } res = res * y[i] % mod; ans = (ans + res) % mod; } return ans; } int main() { cin >> n >> k; for(int i = 1;i <= n;i ++) cin >> x[i] >> y[i]; cout << Lagrange(k) << endl; return 0; }
Example: P4781 Lagrange interpolation