【学习笔记】数学
欧拉函数
\(φ(x)\),小于等于 x 和 x 互质的数的个数。互质时满足积性。
\(x\) 为质数时,\(φ(x)=x-1\)。
多个数
- \(i \bmod x = 0\),\(φ(ix)=i \times x \prod=i \times φ(x)\)。
- \(i \bmod x \not = 0\),\(φ(ix) = φ(i)φ(x)\)。
代码
for(int i = 2;i<=n;++i){
if(!mark[i])e.push_back(i),phi[i] = i-1;
for(int j = 0;j<e.size();++j){
int x = e[j];
if(x*i > n)break;
mark[x*i] = 1;
if(i % x){
phi[i*x] = phi[i]*phi[x];
}else{
phi[i*x] = phi[i]*x;
break;
}
}
}
单个数
\(φ(n)=n*(1-\frac{1}{a1})*(1-\frac{1}{a2})*(1-\frac{1}{a3})*……*(1-\frac{1}{ak})\)
代码
int phi(int n){
int ans = n;
for(int i = 2;i*i<=n;++i){
if(n%i == 0){
ans = ans / i * (i-1);
while(n % i == 0)n /= i;
}
}
if(n > 1)ans = ans / n * (n-1);
return ans;
}
费马小定理:
\(p\) 素,\(a\) 不是 \(p\) 的倍数,\(a^{p-1} ≡ 1\pmod p\)。
故有 \(a ^ b ≡ a ^ {b \mod (p-1)} \pmod p\)。
欧拉定理:
\(p > 0,gcd(a,p)=1\),则有 \(a^{φ(m)} ≡ 1\pmod p\)。
故有:\(a ^ b≡a^{b\mod φ(m) } \pmod m\)。
扩欧拉:
若 \(b \le φ(m), a ^ b ≡ a^b\);
否则 \(a^ b≡ a^{b \mod φ(m)+φ(m)}\)。
威尔逊:
\(n \in N^{+}\),当且仅当 \(n\) 为素数,\((n-1)!≡-1 \pmod n\)。
逆元:
- 扩欧几里得:
代码
int exgcd(int a,int b,int &x,int &y){
if(b == 0){
x = 1, y = 0;
return a;
}
int d = exgcd(b,a%b,x,y);
int t = x;
x = y;
y = t - a/b*y;
return d;
}
/*
b x' + (a % b) y' = gcd
a x + by = gcd
求 x, y
b x' + (a - kb) y' = gcd
b x' + a y' - kb y' = gcd
a y' + b(x' - ky') = gcd
其中 k = a / b
x = y'
y = x' - a / b y'
*/
- 快速幂法
- 递推
代码
inv[0] = inv[1] = 1;
for(int i = 2;i<=n;++i)
inv[i] = (mod - 1ll * inv[mod % i] * (mod / i) % mod) % mod;
/*
p = i * k + t
i * k + t = 0 (mod p)
k + t * inv[i] = 0(mod p)
inv[t] * k + inv[i] = 0(mod p)
-inv[t] * k = inv[i] (mod p)
inv[i] = (p - inv[p % i] * (p / i)) mod p
*/
裴蜀定理
存在 \(x,y\) 使得,\(ax + by = gcd(a, b)\);
任意 \(x,y\) 都有,\(gcd(a,b)|ax + by\)。
CRT
\({x \equiv a_i\pmod {n_i}}\),模数互质,求解 \(x\)。
\(N = \prod n_i, m_i = N / n_i\),\({m_i}^{-1}\) 为 \(m_i\) 在模 \(n\) 意义下的逆元。
\(x = \sum_{i=1}^k a_im_i{m_i}^{-1} \pmod N\)
代码
int n,M = 1,a[N],b[N];
// ∑Mi * ti * ai
inline int exgcd(int a,int b,int &x,int &y){
if(!b){ x = 1; y = 0; return a; }
int d = exgcd(b,a%b,x,y);
int t = x;
x = y; y = t - a / b * y;
return d;
}
int CRT(){
int ans = 0;
for(int i = 1;i<=n;++i){
int m = M / a[i],x = 0,y = 0;
exgcd(m,a[i],x,y);
ans = ((ans + m * x * b[i])%M + M)%M;
}
return ans;
}
signed main(){
n = read();
for(int i = 1;i<=n;++i)a[i] = read(),b[i] = read(),M = M * a[i];
printf("%lld",CRT());
return 0;
}
EXCRT
\({x \equiv a_i\pmod {n_i}}\),模数不互质,求解 \(x\)。
不断合并两个方程。
\(x = n_1 p + a_1 = n_2 q + a_2\),
\(n_1 p - n_2 q = a_2 - a_1\),
由裴蜀定理,\(a_2 - a_1\) 不能被 \(gcd(n_1,n_2)\) 整除时,无解;
否则用扩展欧几里得算出可行解 \((p,q)\);
\(x \equiv b \pmod M\),\(b = n_1 p + a_1,M = \text{lcm}(n_1, n_2)\)。
代码
#include<bits/stdc++.h>
#define print(a) cerr<<#a"="<<(a)<<endl
#define int long long
using namespace std;
const int N = 1e5 + 10;
int n,a[N],m[N];
/*
m1 * p + a1 = m2 * q + a2
m1 * p - m2 * q = a2 - a1
*/
int exgcd(int a,int b,int &x,int &y){
if(b == 0){
x = 1, y = 0;
return a;
}
int d = exgcd(b,a%b,x,y);
int t = x;
x = y;
y = t - a/b*y;
return d;
}
int excrt(){
// if(n == 1){
// if(m[1] > a[1])return a[0] == 0 ? m[0] : a[0];
// else return -1;
// }
int M = m[1], A = a[1] % m[1];
for(int i = 2;i<=n;++i){
a[i] %= m[i];
int x,y,gcd = exgcd(M,m[i],x,y);
int val = a[i] - A;
if(val % gcd != 0)return -1;
int P = m[i] / gcd;
x = ((((__int128)x) * val / gcd) % P + P)%P;
A = M * x + A;
M = M * P;
}
return A == 0 ? A + M : A;
}
void solve(int cas){
scanf("%lld",&n);
for(int i = 1;i<=n;++i)scanf("%lld",&m[i]);
for(int i = 1;i<=n;++i)scanf("%lld",&a[i]);
printf("Case %lld: %lld\n",cas,excrt());
}
signed main(){
int T; scanf("%lld",&T);
for(int i = 1;i<=T;++i)solve(i);
return 0;
}
高斯消元
代码
// 高斯-约旦消元
// https://www.luogu.com.cn/problem/P3389
// 优点:实现行数:无需回带,较简单
// 其实可以判断无解和无数解
#include<bits/stdc++.h>
#define print(a) cout << #a"=" << a << endl
#define debug() cout << "Line:" << __LINE__ << endl
#define sign() puts("----------")
#define double long double
using namespace std;
const int N = 1010;
const double eps = 1e-7;
double a[N][N],ans[N];
int n,m;
int solve(int n,int m){
int r = 1;
for(int c = 1;c<=n;++c){
int mxr = r;
for(int i = r+1;i<=m;++i)if(fabs(a[i][c]) > fabs(a[mxr][c]))
mxr = i;
if(fabs(a[mxr][c]) < eps)continue;
if(mxr ^ r)swap(a[mxr],a[r]);
for(int i = 1;i<=m;++i)if(i ^ r){
for(int j = n+1;j>=c;--j)
a[i][j] -= a[i][c] / a[r][c] * a[r][j];
}
++r;
}
--r;
for(int i = r+1;i<=m;++i)if(fabs(a[i][n+1]) > eps)return -1;
if(r == n){
for(int i = 1;i<=n;++i){
ans[i] = a[i][n+1] / a[i][i];
(fabs(ans[i]) < eps) && (ans[i] = 0);
}
return 0;
}
return m - r;
}
int main(){
scanf("%d",&n);
for(int i = 1;i<=n;++i)
for(int j = 1;j<=n+1;++j)scanf("%Lf",&a[i][j]);
int res = solve(n,n);
if(res == -1 || res > 0)puts("No Solution");
else{
for(int i = 1;i<=n;++i)printf("%.2Lf\n",ans[i] + eps);
}
return 0;
}
插板法
cas1:求 \(x_1+x_2+\cdots+x_k=n\)的正整数解的组数:\(C_{n-1}^{k-1}\)。
cas2:求 \(x_1+x_2+\cdots+x_k=n\)的非负整数解的组数:\(C_{n+k-1}^{k-1}=C_{n+k-1}^n\)。
cas3:求 \(x_1+x_2+\cdots+x_k=n\)解的组数,\(x_i\ge a_i\):
\(x'_i = x_i - a_i,C_{n-\sum a+k-1}^{k-1} = C_{n-\sum a+k-1}^{n-\sum_a}\)。
多重集合
\(S = \{n_i * a_i\},i\in[1,k]\)。
全排列:\(\frac{totn!}{\prod n_i!}\)。
组合(选择 \(r\) 个组成新的多重集的个数):
case1:\(r < n_i, \forall i\)。\(C_{r+k-1}^{k-1}\)。
case2:
\(\forall i \in[i,k],x_i \le n_i,\sum_{i=1}^kx_i=r\)。
容斥。
全局:\(\sum_{i=1}^kx_i=r\),属性:\(x_i\le n_i\)。
\(S_i\) 为满足属性 \(i\) 的集合,\(S'_i\) 为不满足属性 \(i\) 的集合(\(x_i \ge n_i+1\),同插板法中 cas3)。
\(ans = |\bigcap s_i|=|U|-|\bigcup s'_i| = \sum_{popcnt = 0}^k(-1)^{popcnt}\sum_A C_{r-(\sum_{A}n_{A_i}+p)+k-1}^{k-1}\)。
错排
容斥推导:
全集:\(|U| = n!\),属性 \(P_i \not = i\),问题变为求 \(|\bigcup_{i=1}^nS'_i|\)。
\(S'_i\) 即满足 \(P_i = i\) 的排列数量。又 \(|\bigcap_{i=1}^k S_{ai}| = (n-k)!\)。
所以有:\(|\bigcup S'_i|=\sum_{k=1}^n(-1)^{k-1} \sum_{A}|\bigcap_{i=1}^kS_{ai}|=\sum_{i=1}^n(-1)^{k-1}C_{n}^{k}(n-k)!=\sum_{i=1}^n(-1)^{k-1}\frac{n!}{k!}=n!\sum_{k=1}^{n}\frac{(-1)^{k-1}}{k!}\)。
因此 \(n\) 的错位排列数为:\(D_n = n! - n ! \sum_{k=1}^n\frac{(-1)^{k-1}}{k!}=n!\sum_{i=0}^n\frac{(-1)^{k}}{k!}\)。
递推:
\(D_n=(n-1)(D_{n-1}+D_{n-2})\)。
抽屉原理
构造中 trick
组合数推导
二项式定理
\((a+b)^n = \sum_{i=0}^{n}C_{n}^{i}a^{n-i}b^{i}\)
Catalan 数
\(C_n = \sum_{i=0}^{n-1}C_{i}C_{n-1-i},C_0 = 1\);
\(C_n = \frac{C_{2n}^n}{n+1}\);
\(C_n = C_{2n}^n - C_{2n}^{n+1}, n \ge 0\);
\(C_n = \frac{4n-2}{n+1}C_{n-1},n > 0, C_0 = 1\)。
应用:
- 路径计数问题:有一个大小为 \(n\times n\) 的方格图,左下角为 \((0, 0)\),右上角为 \((n, n)\)。从左下角开始,每次都只能向右或者向上走一单位,不走到对角线 \(y=x\) 上方(但可以触碰)的情况下,到达右上角的路径总数为
\(C_n\)。 - 圆内不相交弦计数问题:圆上有 \(2n\) 个点,将这些点成对连接起来且使得所得到的 \(n\) 条线段两两不交的方案数是 \(C_n\)。
- 三角剖分计数问题:对角线不相交的情况下,将一个凸 \((n+2)\) 边形区域分成三角形区域的方法数为 \(C_n\)。
- 二叉树计数问题:含有 \(n\) 个结点的形态不同的二叉树数目为 \(C_n\)。等价地,含有 \(n\) 个非叶结点的形态不同的满二叉树数目为 \(C_{n}\)。
- 括号序列计数问题:由 \(n\) 对括号构成的合法括号序列数为 \(C_n\)。
- 出栈序列计数问题:一个栈(无穷大)的进栈序列为 \(1,2,3, \ldots ,n\),合法出栈序列的数目为 \(C_n\)。
- 数列计数问题:\(n\) 个 \(+1\),\(n\) 个 \(-1\),满足所有前缀和 \(\ge 0\) 的序列个数为 \(C_n\)。

浙公网安备 33010602011771号