Математические алгоритмы.
Продолжение
MTUCI ICPC
Ликбез по линейной алгебре

Матричное умножение
Умножение матриц. Код
void matmul(const vector<vector<int>>& a,
const vector<vector<int>>& b,
vector<vector<int>>& c){
for (int i=0;i<a.size();++i){
for (int j=0;j<b[0].size();++j){
for (int k=0;k<b.size();++k){
c[i][j]+=a[i][k]*b[k][j];
}
}
}
return;
}Свойства операций над матрицами
- Сумма матриц AA и BB тоже является матрицей: C = A+B: C_{ij} = A_{ij} + B_{ij}C=A+B:Cij=Aij+Bij.
- Сумма матриц коммутативна: A+B = B+AA+B=B+A.
- Сумма матриц ассоциативна: (A+B)+C = A+(B+C)(A+B)+C=A+(B+C).
- Умножение матриц ассоциативно: (AB)C = A(BC) = ABC(AB)C=A(BC)=ABC.
- Умножение матриц в общем случае не коммутативно.
Полезные примеры матриц
Равномерное увеличение в n раз:
Перемена координат местами:
Матрица поворота:
Единичная матрица:
Примеры решения задач с помощью матриц
Вычисление n-ого числа Фиббоначи:
Поиск k-цикла в графе
Рекуррентные формулы в общем виде
Линейные уравнения и метод Гаусса
- поменять два уравнения местами,
- домножить любое уравнение на ненулевую константу,
- вычесть из одного уравнения другое.
Список операций:
Цель:
Решение СЛАУ методов Гаусса. Код
void gauss(vector<vector<double>>& a,
vector<double>& b){
for (int i=0;i<a.size();++i){
double cc = 1/a[i][i];
b[i]*=cc;
for (int j=0;j<a.size();j++){
a[i][j]*=cc;
}
for (int j=0;j<a.size();j++){
double c2 = a[j][i];
if (j!=i){
b[j]-=c2*b[i];
for (int k=0;k<a.size();++k){
a[j][k]-=c2*a[i][k];
}
}
}
}
return;
}Интерполяция.
Интерполяционный многочлен Лагранжа
Суть интерполяции

Как считать:
Задача интерполяции как СЛАУ
Длинная арифметика и многочлены
Как хранить?
vector<int> digits a; //разряды нашего числа
int base = 10; // может быть любой
// 123459 = {9,5,4,3,2,1}
1 000 000 000 000 = [1000][0]_1e9Как складывать? По разрядам, а потом
const int base = 10;
vector<int> normalize(vector<int> a) {
int carry = 0;
for (int &x : a) {
x += carry;
carry = x / base;
x %= base;
}
while (carry > 0) {
a.push_back(carry % base);
carry /= base;
}
return a;
}
Ускоряем умножение
Алгоритм Карацубы:
Алгоритм Карацубы. Код
Кольцо вычетов по модулю

Кольца вычетов по модулю
Расширенный алгоритм Евклида

Расширенный алгоритм Евклида. Код
Поиск обратного по модулю
С помощью алгоритма Евклида:
Малая теорема Ферма (для простого модуля)
Теорема Эйлера (для любого модуля)
Диофантовы уравнения
Общий вид уравнения:
Еще раз взглянем на расширенный алгоритм Евклида:
Решение:
Факторизация чисел
- Стандартный алгоритм за sqrt(n)
- ро-Алгоритм Полларда O(n^(1/4)logn)
- Алгоритм Ферма
- ...
Ро-алгоритм Полларда

База алгоритма - парадокс дня рождения
Наша "случайная" функция:
Ро-Алгоритм Полларда

Буква Ро на функциональном графе
Ро-алгоритм Полларда. Код
define long long ll;
inline ll f(ll x, ll n) { return (__int128_t) (x + 1) * (x + 1) % n; }
ll find_divisor(ll n, ll seed = 1) {
ll x = seed, y = seed;
ll d = 1;
while (d == 1 || d == n) {
// двигаем первый указатель на шаг
y = f(y);
// а второй -- на два
x = f(f(x));
// пытаемся найти общий делитель
d = gcd(abs(x - y), n);
}
return d;
}Применение факторизации
- Взлом шифров (RSA)
- Быстрый подсчет функции Эйлера
Комбинаторика
Вероятность
Марковские цепи
Вы устроились на работу в крупную IT компанию, но, придя в офис, обнаружили, что лифт едет на случайные этажи с определенными вероятностями перехода. Как узнать распределение вероятности этажа, на котором вы окажетесь после k-поездок на этом лифте?
Быстрое вычисление факториала по модулю


Быстрое вычисление факториала по модулю. Код
int calc(int n, int p){
int res=1;
int t=1;
while(n>1){
if (n/p%2){
t = p - 1;
}
else{
t = 1
};
res = res * t % p;
for (int i=2;i<=n%p;++i){
res = res * i % p;
}
n/=p;
}
return res % p;
}Полезные формулы и фишки
Advanced Math Algorithms
By Fleming Kris
Advanced Math Algorithms
- 228