文章目录
1.数学
1.1矩阵
1.1.1高斯消元
代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
const int maxn = 1e5 + 10;
const ll mod = 1e9 + 7;
const int inf = 1e9;
const double eps = 1e-10;
int n;
double a[110][110];
int main() {
__;
cin >> n;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n + 1; ++j) {
cin >> a[i][j];
}
}
for (int i = 1; i <= n; ++i) {
int r = i;
for (int j = i + 1; j <= n; ++j)
if (fabs(a[j][i]) - fabs(a[r][i]) >= eps)r = j;
for (int j = 1; j <= n + 1; ++j)
swap(a[i][j], a[r][j]);
if (fabs(a[r][r]) <= eps) {
cout << "No Solution" << endl;
return 0;
}
for (int j = i + 1; j <= n + 1; ++j) {
a[i][j] /= a[i][i];
}
for (int j = 1; j <= n; ++j) {
if (i != j) {
for (int k = i + 1; k <= n + 1; ++k) {
a[j][k] -= a[j][i] * a[i][k];
}
}
}
}
for (int i = 1; i <= n; ++i)cout << fixed << setprecision(2) << a[i][n + 1] << endl;
return 0;
}
1.1.2矩阵快速幂
struct matrix {
ll num[5][5];
int m, mod;//需要赋初值或设为全局变量
matrix() { memset(num, 0, sizeof num); }
matrix operator*(const matrix &x) {
matrix c;
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= m; ++j) {
for (int k = 1; k <= m; ++k) {
c.num[i][j] = (c.num[i][j] + num[i][k] * x.num[k][j] + mod) % mod;
}
}
}
return c;
}
matrix &operator=(const matrix &x) {
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= m; ++j) {
num[i][j] = x.num[i][j];
}
}
return *this;
}
};
matrix pow_mod(matrix &x, ll k) {
matrix ans;
for (int i = 1; i <= x.m; ++i) {
ans.num[i][i] = 1;
}
while (k) {
if (k & 1)ans = ans * x;
x = x * x;
k >>= 1;
}
return ans;
}
1.2整除与剩余
1.2.1欧几里得算法
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
1.2.2扩展欧几里得算法
求取ax + by = gcd(a, b)
代码:
void e_gcd(int a, int b, int &x, int &y) {
if (b == 0) {
x = 1;
y = 0;
return;
}
e_gcd(b, a % b, y, x);
y -= (a / b) * x;
}
/*
解得ax+by=gcd(a,b)的值,特解:
x0 = x * c / gcd(a, b);
y0 = y * c / gcd(a, b);
所有解即为:
x = x0 + k * b / gcd(a, b);
y = y0 - k * a / gcd(a, b);
*/
1.2.3线性乘法逆元
/*1 - n的乘法逆元,m为模数*/
ni[1] = 1;
for (int i = 2; i <= n; ++i) {
ni[i] = (m - m / i) * ni[m % i] % m;
}
1.3素数*
1.3.1素数筛法
线性筛素数O(n):
bool vis[maxn];
int ans[maxn], tot;
void get_prime(int n) {
memset(vis, 1, sizeof(vis));
vis[0] = vis[1] = 0;
for (int i = 2; i <= n; ++i) {
if (vis[i]) {
++tot;
ans[tot] = i;
}
for (int j = 1; ((j <= tot) && (i * ans[j] <= n)); ++j) {
vis[i * ans[j]] = 0;
if (i % ans[j] == 0)break;
}
}
}
1.3.2素数判定
素数测试(Miller-Rabin算法):
ll mult_mod(ll a, ll b, ll c) {
a %= c;
b %= c;
ll ret = 0;
ll tmp = a;
while (b) {
if (b & 1) {
ret += tmp;
if (ret > c) ret -= c;
}
tmp <<= 1;
if (tmp > c) tmp -= c;
b >>= 1;
}
return ret;
}
ll pow_mod(ll a, ll b, ll m) {
ll ans = 1;
while (b) {
if (b & 1)ans = ans * a % m;
a = a * a % m;
b >>= 1;
}
return ans;
}
bool check(ll a, ll n, ll x, ll t) {
ll ret = pow_mod(a, x, n);
ll last = ret;
for (int i = 1; i <= t; i++) {
ret = mult_mod(ret, ret, n);
if (ret == 1 && last != 1 && last != n - 1) return true;
last = ret;
}
if (ret != 1) return true;
else return false;
}
const int S = 20;//测试次数
bool is_prime(ll n) {
if (n < 2) return false;
if (n == 2) return true;
if ((n & 1) == 0) return false;
ll x = n - 1;
ll t = 0;
while ((x & 1) == 0) {
x >>= 1;
t++;
}
srand(time(NULL));
for (int i = 0; i < S; i++) {
ll a = rand() % (n - 1) + 1;
if (check(a, n, x, t)) return false;
}
return true;
}
1.3.3质因数分解
/*
质因数分解:
n表示待分解的整数
&tot表示不同质因数的个数
p[i]表示第i个质因数的值
q[i]表示第i个质因数的指数
调用方式 factor(n,p,q,tot);
*/
void factor(ll n, ll *p, ll *q, int &tot) {
ll temp, now;
temp = (int) sqrt(n);
tot = 0;
now = n;
for (int i = 2; i <= temp; ++i) {
if (now % i == 0) {
p[++tot] = i;
q[tot] = 0;
while (now % i == 0) {
++q[tot];
now /= i;
}
}
}
if (now != 1) {
p[++tot] = now;
q[tot] = 1;
}
}
1.4欧拉函数
1.4.1计算欧拉函数
int euler_phi(int n) {
int m = (int) sqrt(n + 0.5);
int ans = n;
for (int i = 2; i <= m; ++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;
}
1.4.2筛法构造欧拉函数表
int phi[maxn];
void phi_table(int n) {
phi[1] = 1;
for (int i = 2; i <= n; i++) {
if (!phi[i]) {
for (int j = i; j <= n; j += i) {
if (!phi[j])phi[j] = j;
phi[j] = (phi[j] / i) * (i - 1);
}
}
}
}
1.5其他
1.5.1快速幂
#define ll long long
ll pow_mod(ll a, ll b, ll m) {
ll ans = 1;
while (b) {
if (b & 1)ans = ans * a % m;
a = a * a % m;
b >>= 1;
}
return ans;
}
1.5.2 卢卡斯定理
卢卡斯定理求C(n,m)%p的值
注意:p一定为一个不大的素数
先调用init(p);计算所有阶乘的值
然后lucas(n,m,p)即为所求
const int maxn = 1e6 + 10;
ll f[maxn];
void init(ll p) {
f[0] = 1;
for (int i = 1; i <= p; ++i)
f[i] = f[i - 1] * i % p;
}
ll pow_mod(ll a, ll b, ll mod) {
ll ans = 1;
while (b > 0) {
if (b & 1)ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
ll lucas(ll n, ll m, ll p) {
ll ans = 1;
while (n && m) {
ll a = n % p, b = m % p;
if (a < b)return 0;
ans = ans * f[a] % p * pow_mod(f[b] * f[a - b] % p, p - 2, p) % p;
n /= p;
m /= p;
}
return ans;
}
1.5.3 高精度整数(Java)
import java.io.*;
import java.util.*;
import java.math.*;
public class Main {
public static void main(String args[]) {
Scanner cin = new Scanner(System.in);
BigInteger a, b;
//以文件EOF结束
while (cin.hasNext()) {
a = cin.nextBigInteger();
b = cin.nextBigInteger();
System.out.println(a.add(b)); //大整数加法
System.out.println(a.subtract(b)); //大整数减法
System.out.println(a.multiply(b)); //大整数乘法
System.out.println(a.divide(b)); //大整数除法(取整)
System.out.println(a.remainder(b)); //大整数取模
//大整数的比较
if (a.compareTo(b) == 0) System.out.println("a == b"); //大整数a==b
else if (a.compareTo(b) > 0) System.out.println("a > b"); //大整数a>b
else if (a.compareTo(b) < 0) System.out.println("a < b"); //大整数a<b
//大整数绝对值
System.out.println(a.abs()); //大整数a的绝对值
//大整数的幂
int exponent = 10;
System.out.println(a.pow(exponent)); //大整数a的exponent次幂
//返回大整数十进制的字符串表示
System.out.println(a.toString());
//返回大整数p进制的字符串表示
int p = 8;
System.out.println(a.toString(p));
}
}
}
1.5.4 斐波那契数列求循环节
//先调用getprime()
#define ll unsigned long long
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b) {
return a / gcd(a, b) * b;
}
struct Matrix {
ll mat[2][2];
Matrix() { memset(mat, 0, sizeof mat); }
};
Matrix mul_M(Matrix a, Matrix b, ll mod) {
Matrix ans;
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 2; ++j) {
ans.mat[i][j] = 0;
for (int k = 0; k < 2; ++k) {
ans.mat[i][j] += a.mat[i][k] * b.mat[k][j] % mod;
if (ans.mat[i][j] >= mod)ans.mat[i][j] -= mod;
}
}
}
return ans;
}
Matrix pow_M(Matrix a, ll n, ll mod) {
Matrix ans;
for (int i = 0; i < 2; ++i) ans.mat[i][i] = 1;
Matrix tmp = a;
while (n) {
if (n & 1)ans = mul_M(ans, tmp, mod);
tmp = mul_M(tmp, tmp, mod);
n >>= 1;
}
return ans;
}
ll pow_m(ll a, ll n, ll mod) {
ll ans = 1, tmp = a % mod;
while (n) {
if (n & 1)ans = ans * tmp % mod;
tmp = tmp * tmp % mod;
n >>= 1;
}
return ans;
}
const int maxn = 1e6 + 10;
int prime[maxn];
void getprime() {
memset(prime, 0, sizeof prime);
for (int i = 2; i <= maxn; ++i) {
if (!prime[i])prime[++prime[0]] = i;
for (int j = 1; j <= prime[0] && prime[j] * i <= maxn; ++j) {
prime[prime[j] * i] = 1;
if (i % prime[j] == 0)break;
}
}
}
ll factor[100][2];
int fatcnt;
int getfactors(ll x) {
fatcnt = 0;
ll tmp = x;
for (int i = 1; prime[i] * prime[i] <= tmp; ++i) {
factor[fatcnt][1] = 0;
if (tmp % prime[i] == 0) {
factor[fatcnt][0] = prime[i];
while (tmp % prime[i] == 0) {
factor[fatcnt][1]++;
tmp /= prime[i];
}
fatcnt++;
}
}
if (tmp != 1) {
factor[fatcnt][0] = tmp;
factor[fatcnt++][1] = 1;
}
return fatcnt;
}
int legendre(ll a, ll p) {
if (pow_m(a, (p - 1) >> 1, p) == 1)return 1;
else return -1;
}
int f0 = 1;
int f1 = 1;
ll getfib(ll n, ll mod) {
if (mod == 1)return 0;
Matrix A;
A.mat[0][0] = 0;
A.mat[1][0] = 1;
A.mat[0][1] = 1;
A.mat[1][1] = 1;
Matrix B = pow_M(A, n, mod);
ll ans = f0 * B.mat[0][0] + f1 * B.mat[1][0];
return ans % mod;
}
ll fac[maxn];
ll G(ll p) {
ll num;
if (legendre(5, p) == 1)num = p - 1;
else num = 2 * (p + 1);
int cnt = 0;
for (ll i = 1; i * i <= num; ++i) {
if (num % i == 0) {
fac[cnt++] = i;
if (i * i != num) {
fac[cnt++] = num / i;
}
}
}
sort(fac, fac + cnt);
ll ans;
for (int i = 0; i < cnt; ++i) {
if (getfib(fac[i], p) == f0 && getfib(fac[i] + 1, p) == f1) {
ans = fac[i];
break;
}
}
return ans;
}
ll find_loop(ll n) {
getfactors(n);
ll ans = 1;
for (int i = 0; i < fatcnt; ++i) {
ll record = 1;
if (factor[i][0] == 2)record = 3;
else if (factor[i][0] == 3)record = 8;
else if (factor[i][0] == 5)record = 20;
else record = G(factor[i][0]);
for (int j = 1; j < factor[i][1]; ++j) {
record *= factor[i][0];
}
ans = lcm(ans, record);
}
return ans;
}
1.5.5 FFT
stl complex实现:
const int maxn = 5e5 + 10;
const ld PI = acos(-1.0);
#define cp complex<double>
int rev[maxn], ans[maxn];
cp A[maxn], B[maxn];
void FFT(cp *a, int n, int inv) {
int bit = 0;
while ((1 << bit) < n)++bit;
for (int i = 0; i <= n - 1; ++i) {
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
if (i < rev[i])swap(a[i], a[rev[i]]);
}
for (int len = 2; len <= n; len <<= 1) {
int mid = len >> 1;
cp unit(cos(PI / mid), inv * sin(PI / mid));
for (int i = 0; i < n; i += len) {
cp omega(1, 0);
for (int j = 0; j < mid; ++j, omega *= unit) {
cp x = a[i + j], y = omega * a[i + j + mid];
a[i + j] = x + y;
a[i + j + mid] = x - y;
}
}
}
if (inv == -1) {
for (int i = 0; i <= n; ++i)a[i] /= n;
}
}
// use FFT
// Array A[0...n-1]
// Array B[0...m-1]
void mul() {
int bitn = 1;
while (bitn < n + m)bitn <<= 1;
FFT(A, bitn, 1);
FFT(B, bitn, 1);
for (int i = 0; i < bitn; ++i) {
A[i] = A[i] * B[i];
}
FFT(A, bitn, -1);
for (int i = 0; i < n + m - 1; ++i) {
ans[i] += (int) (A[i].real() + 0.5);
}
}
手写complex:
const int maxn = 2e6 + 10;
const double PI = acos(-1.0);
struct Complex {
double x, y;
Complex(double _x = 0.0, double _y = 0.0) {
x = _x;
y = _y;
}
Complex operator-(const Complex &b) const {
return Complex(x - b.x, y - b.y);
}
Complex operator+(const Complex &b) const {
return Complex(x + b.x, y + b.y);
}
Complex operator*(const Complex &b) const {
return Complex(x * b.x - y * b.y, x * b.y + y * b.x);
}
};
int rev[maxn];
#define cp Complex
void FFT(cp *a, int n, int inv) {
int bit = 0;
while ((1 << bit) < n)++bit;
for (int i = 0; i <= n - 1; ++i) {
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));
if (i < rev[i])swap(a[i], a[rev[i]]);
}
for (int len = 2; len <= n; len <<= 1) {
int mid = len >> 1;
cp unit(cos(PI / mid), inv * sin(PI / mid));
for (int i = 0; i < n; i += len) {
cp omega(1, 0);
for (int j = 0; j < mid; ++j, omega = omega * unit) {
cp x = a[i + j], y = omega * a[i + j + mid];
a[i + j] = x + y;
a[i + j + mid] = x - y;
}
}
}
if (inv == -1) {
for (int i = 0; i <= n; ++i)a[i].x /= n;
}
}
1.5.6 FWT
const int maxn = 5e5 + 10;
const int mod = 998244353;
const int OR = 1, AND = 2, XOR = 3, XNOR = 4;
int add(int x, int y) {
return (x += y) >= mod ? x - mod : x;
}
int sub(int x, int y) {
return (x -= y) < 0 ? x + mod : x;
}
void fwt(int op, int *a, int n, int rev) {
for (int d = 1; d < n; d <<= 1) {
for (int m = d << 1, i = 0; i < n; i += m) {
for (int j = 0; j < d; ++j) {
int x = a[i + j], y = a[i + j + d];
if (rev == 1) {
if (op == OR)a[i + j + d] = add(y, x);
if (op == AND)a[i + j] = add(x, y);
if (op == XOR)a[i + j] = add(x, y), a[i + j + d] = sub(x, y);
if (op == XNOR)a[i + j] = sub(y, x), a[i + j + d] = add(x, y);
} else {
ll inv2 = (mod + 1) >> 1;
if (op == OR)a[i + j + d] = sub(y, x);
if (op == AND)a[i + j] = sub(x, y);
if (op == XOR)a[i + j] = 1ll * add(x, y) * inv2 % mod, a[i + j + d] = 1ll * sub(x, y) * inv2 % mod;
if (op == XNOR)a[i + j] = 1ll * sub(y, x) * inv2 % mod, a[i + j + d] = 1ll * add(x, y) * inv2 % mod;
}
}
}
}
}
int A[maxn], B[maxn];
void mul(int op, int *a, int n, int *b, int m, int *ans) {
int bitn = 1;
while (bitn < (n + m))bitn <<= 1;
for (int i = 0; i < bitn; ++i)A[i] = a[i], B[i] = b[i];
fwt(op, A, bitn, 1);
fwt(op, B, bitn, 1);
for (int i = 0; i < bitn; ++i)ans[i] = 1ll * A[i] * B[i] % mod;
fwt(op, ans, bitn, -1);
}