Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma GCC optimize("O3")
- #define _SCL_SECURE_NO_WARNINGS
- #define _CRT_SECURE_NO_WARNINGS
- #include <cassert>
- #include <ciso646>
- #include <climits>
- #include <cmath>
- #include <cstdint>
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <ctime>
- #include <array>
- #include <bitset>
- #include <deque>
- #include <forward_list>
- #include <list>
- #include <map>
- #include <queue>
- #include <set>
- #include <stack>
- #include <unordered_map>
- #include <unordered_set>
- #include <vector>
- #include <algorithm>
- #include <complex>
- #include <functional>
- #include <initializer_list>
- #include <iterator>
- #include <limits>
- #include <locale>
- #include <numeric>
- #include <regex>
- #include <string>
- #include <utility>
- #include <fstream>
- #include <iostream>
- #include <sstream>
- #include <iomanip>
- using namespace std;
- typedef long long ll;
- typedef long double ld;
- #define pb push_back
- #define mp make_pair
- #define x first
- #define y second
- #define speedup cout.tie(nullptr);cin.tie(nullptr);ios_base::sync_with_stdio(false)
- #define coutdouble cout<<setprecision(20);cout<<fixed
- #define all(v) (v).begin(),(v).end()
- /*------CommentInInteractive--------*/
- #define endl "\n"
- /*----------------------------------*/
- const int INF = 2 * 1000 * 1000 * 1000 + 322;
- const ll LLINF = 2LL * 1000LL * 1000LL * 1000LL * 1000LL * 1000LL * 1000LL;
- const int MOD = 1000 * 1000 * 1000 + 7;
- const int RMOD = MOD - 2;
- const int N = 100 + 4;
- const int P1M = 1336337; //Large prime ( ~1M )
- const int P1K = 1009; //Big prime ( ~1K )
- const ld EPS = 1e-9;
- const ld PI = 3.1415926535897932384626433832795;
- /*------------------------------------------------IO_OPERATORS---------------------------------------------*/
- template<typename T, typename U> inline ostream &operator << (ostream &_out, const pair<T, U> &_p) { _out << _p.first << ' ' << _p.second; return _out; }
- template<typename T, typename U> inline istream &operator >> (istream &_in, pair<T, U> &_p) { _in >> _p.first >> _p.second; return _in; }
- template<typename T> inline ostream &operator << (ostream &_out, const vector<T> &_v) { if (_v.empty()) return _out; _out << _v.front(); for (auto _it = ++_v.begin(); _it != _v.end(); ++_it) _out << ' ' << *_it; return _out; }
- template<typename T> inline istream &operator >> (istream &_in, vector<T> &_v) { for (auto &_i : _v) _in >> _i; return _in; }
- template<typename T> inline ostream &operator << (ostream &_out, const set<T> &_s) { if (_s.empty()) return _out; _out << *_s.begin(); for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) _out << ' ' << *_it; return _out; }
- template<typename T> inline ostream &operator << (ostream &_out, const multiset<T> &_s) { if (_s.empty()) return _out; _out << *_s.begin(); for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) _out << ' ' << *_it; return _out; }
- template<typename T> inline ostream &operator << (ostream &_out, const unordered_set<T> &_s) { if (_s.empty()) return _out; _out << *_s.begin(); for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) _out << ' ' << *_it; return _out; }
- template<typename T> inline ostream &operator << (ostream &_out, const unordered_multiset<T> &_s) { if (_s.empty()) return _out; _out << *_s.begin(); for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) _out << ' ' << *_it; return _out; }
- template<typename T, typename U> inline ostream &operator << (ostream &_out, const map<T, U> &_m) { if (_m.empty()) return _out; _out << '(' << _m.begin()->first << ": " << _m.begin()->second << ')'; for (auto _it = ++_m.begin(); _it != _m.end(); ++_it) _out << ", (" << _it->first << ": " << _it->second << ')'; return _out; }
- template<typename T, typename U> inline ostream &operator << (ostream &_out, const unordered_map<T, U> &_m) { if (_m.empty()) return _out; _out << '(' << _m.begin()->first << ": " << _m.begin()->second << ')'; for (auto _it = ++_m.begin(); _it != _m.end(); ++_it) _out << ", (" << _it->first << ": " << _it->second << ')'; return _out; }
- /*--------------------------------------------------IO_FILES-----------------------------------------------*/
- const char * infile =
- #ifdef LOCAL
- "input.txt"
- #else
- ""
- #endif //LOCAL
- ;
- const char * outfile =
- #ifdef LOCAL
- ""
- #else
- ""
- #endif //LOCAL
- ;
- /*----------------------------------------------------MATHS------------------------------------------------*/
- inline int gcd(int a, int b) { while (b) { int tmp = a%b; a = b; b = tmp; } return a; }
- inline int gcd(vector<int> a) { while (a.size() > 1) { int tmp1 = a.back(), tmp2 = a.back(); a.pop_back(), a.pop_back(); a.push_back(gcd(tmp1, tmp2)); } return a[0]; }
- inline ll lcm(int a, int b) { return (ll)a*(ll)b / gcd(a, b); }
- inline ll pwm(ll xx, ll pow) { ll mlt = 1; while (pow) { if (pow & 1) { mlt *= xx; xx *= xx; pow >>= 1; xx %= MOD; mlt %= MOD; } else { pow >>= 1; xx *= xx; xx %= MOD; } }return mlt; }
- inline ll pw(ll xx, int pow) { ll mlt = 1; while (pow) { if (pow & 1) { mlt *= xx; xx *= xx; pow >>= 1; } else { pow >>= 1; xx *= xx; } }return mlt; }
- inline ll rev(ll r) { return pwm(r, RMOD); }
- /*--------------------------------------------------------------------------------------------------------*/
- #define MAX_PRINT 20
- #define LEN 5000
- #define eps 1e-17
- union bit_double {
- double val;
- ll bits;
- };
- inline void print_mat(double *mat, int n, int m) { // n - #columns, m - #rows
- int prt_n = (n > MAX_PRINT) ? MAX_PRINT : n;
- int prt_m = (m > MAX_PRINT) ? MAX_PRINT : m;
- int i, j;
- for (i = 0; i < prt_m; ++i, mat += n) {
- for (j = 0; j < prt_n; ++j)
- cout << setw(10) << mat[j] << " ";
- cout << endl;
- }
- }
- inline int input_mat(double *mat, int n, int m, const char *file) {
- double *end = mat + m * n;
- for (; mat < end && cin >> *mat; ++mat);
- return 0;
- }
- inline double gen_func(int i, int j) {
- double res = 1. / (i + 1 + j);
- //double res = i + j + 1;
- return res;
- }
- inline void gen(double *mat, int n, int m) { // n - #columns, m - #rows
- int i, j;
- memset(mat, 0, n * n * sizeof(double));
- for (i = 0; i < m; ++i) {
- for (j = 0; j < n; ++j) {
- mat[i *n + j] = gen_func(i, j);
- }
- }
- }
- inline void transp(double *A, int n) {
- for (int i = 0; i < n; ++i) {
- for (int j = i + 1; j < n; ++j) {
- double tmp = A[i *n + j];
- A[i * n + j] = A[j * n + i];
- A[j * n + i] = tmp;
- }
- }
- }
- inline void residial_cnt(double *lm, double *rm, int n, double * rs_1, double * rs_inf) {
- static double norm[LEN];
- const double *end = rm + n * n, *begin = rm;
- double *cur = lm;
- double cur_elem = -1, cur_s = 0, max_s = -1;
- int i, j, k;
- memset(norm, 0, n * sizeof(double));
- switch (i = n & 3) {
- case 3:
- for (j = 0, k = 0; rm < end; ++rm, ++j) {
- cur_elem += cur[j] * (*rm);
- if (j == n - 1) {
- norm[k] += cur_elem;
- j = -1, ++k;
- cur_s += fabs(cur_elem), cur_elem = 0;
- }
- }
- cur += n, rm = (double *)begin;
- max_s = cur_s > max_s ? cur_s : max_s;
- cur_s = 0;
- case 2:
- for (j = 0, k = 0; rm < end; ++rm, ++j) {
- cur_elem += cur[j] * (*rm);
- if (j == n - 1) {
- norm[k] += cur_elem;
- j = -1, ++k;
- cur_s += fabs(cur_elem), cur_elem = (i - 2) == k ? -1 : 0;
- }
- }
- cur += n, rm = (double *)begin;
- max_s = cur_s > max_s ? cur_s : max_s;
- cur_s = 0;
- case 1:
- for (j = 0, k = 0; rm < end; ++rm, ++j) {
- cur_elem += cur[j] * (*rm);
- if (j == n - 1) {
- norm[k] += cur_elem;
- j = -1, ++k;
- cur_s += fabs(cur_elem), cur_elem = (i - 1) == k ? -1 : 0;
- }
- }
- cur += n, rm = (double *)begin;
- max_s = cur_s > max_s ? cur_s : max_s;
- cur_s = 0;
- }
- for (; i < n;) {
- // 0
- for (j = 0, k = 0; rm < end; ++rm, ++j) {
- cur_elem += cur[j] * (*rm);
- if (j == n - 1) {
- norm[k] += cur_elem;
- j = -1, ++k;
- cur_s += fabs(cur_elem), cur_elem = i == k ? -1 : 0;
- }
- }
- cur += n, rm = (double *)begin;
- max_s = cur_s > max_s ? cur_s : max_s;
- cur_s = 0; ++i;
- //1
- for (j = 0, k = 0; rm < end; ++rm, ++j) {
- cur_elem += cur[j] * (*rm);
- if (j == n - 1) {
- norm[k] += cur_elem;
- j = -1, ++k;
- cur_s += fabs(cur_elem), cur_elem = i == k ? -1 : 0;
- }
- }
- cur += n, rm = (double *)begin;
- max_s = cur_s > max_s ? cur_s : max_s;
- cur_s = 0; ++i;
- //2
- for (j = 0, k = 0; rm < end; ++rm, ++j) {
- cur_elem += cur[j] * (*rm);
- if (j == n - 1) {
- norm[k] += cur_elem;
- j = -1, ++k;
- cur_s += fabs(cur_elem), cur_elem = i == k ? -1 : 0;
- }
- }
- cur += n, rm = (double *)begin;
- max_s = cur_s > max_s ? cur_s : max_s;
- cur_s = 0; ++i;
- //3
- for (j = 0, k = 0; rm < end; ++rm, ++j) {
- cur_elem += cur[j] * (*rm);
- if (j == n - 1) {
- norm[k] += cur_elem;
- j = -1, ++k;
- cur_s += fabs(cur_elem), cur_elem = i == k ? -1 : 0;
- }
- }
- cur += n, rm = (double *)begin;
- max_s = cur_s > max_s ? cur_s : max_s;
- cur_s = 0; ++i;
- }
- *rs_1 = max_s;
- for (i = 1; i < n; *rs_inf = *rs_inf > norm[i] ? *rs_inf : norm[i], ++i);
- }
- inline void mul_1(double *A, int i, int j, double alfa, double beta, int n) {
- int k;
- double *r1 = A + i*n, *r2 = r1 + j*n;
- double elem_r1, elem_r2;
- for (k = i; k < n; ++k) {
- elem_r1 = r1[k], elem_r2 = r2[k];
- r1[k] = r1[k] * alfa - elem_r2 * beta;
- r2[k] = r2[k] * alfa + elem_r1 * beta;
- }
- }
- inline void mul_2(double *A, int i, int j, double alfa, double beta, int n) {
- int k;
- double *r1 = A + i*n, *r2 = A + j*n;
- double elem_r1, elem_r2;
- for (k = 0; k < n; ++k) {
- elem_r1 = r1[k], elem_r2 = r2[k];
- r1[k] = r1[k] * alfa + elem_r2 * beta;
- r2[k] = r2[k] * alfa - elem_r1 * beta;
- }
- }
- inline bool inv_U(double *U, int n) {
- static double cur_row[LEN];
- double *cur, *sub_r;
- double factor;
- int i, j, k;
- cur = U + n*(n - 1);
- for (i = n - 1; i >= 0; --i, cur -= n) {
- memset(cur_row + i, 0, (n - i) * sizeof(double));
- cur_row[i] = 1;
- sub_r = U + i*n;
- for (j = i + 1; j < n; ++j) {
- double coef = cur[j];
- sub_r += n;
- for (k = j; k < n; ++k) {
- cur_row[k] -= coef * sub_r[k];
- }
- }
- if (fabs(cur[i]) < eps) {
- return false;
- }
- for (k = i, factor = cur[i]; k < n; ++k) {
- cur_row[k] /= factor;
- }
- memcpy(cur + i, cur_row + i, (n - i)* sizeof(double));
- }
- return true;
- } // U = U^(-1)
- inline void QRD_upg(double *A, int n) {
- int i, j;
- double cos_fi, sin_fi;
- double c_v, c_v2, factor;
- double *cur = A;
- ll *cur_ll = (ll *)A;
- for (i = 0; i < n - 1; ++i, cur += n + 1, cur_ll += n + 1) {
- for (j = 1; j < n - i; ++j) {
- c_v = *cur, c_v2 = cur[j*n];
- if (fabs(c_v2) < eps) {
- cur_ll[j*n] |= 3;
- continue;
- }
- factor = (c_v * c_v + c_v2 * c_v2);
- sin_fi = -(cos_fi = sqrt(1. / factor));
- sin_fi *= c_v2, cos_fi *= c_v;
- mul_1(A, i, j, cos_fi, sin_fi, n);// A -> cur ?
- if (fabs(cos_fi) < fabs(sin_fi)) { // ...ab, a = (is this sin_fi ? 1 : 0), b = (other func > 0 ? 1 : 0)
- cur[j*n] = cos_fi;
- if (sin_fi > 0) {//..01
- cur_ll[j*n] |= 1;
- cur_ll[j*n] &= ~2;
- }
- else {//...00
- cur_ll[j*n] &= ~3;
- }
- }
- else {
- cur[j*n] = sin_fi;
- if (cos_fi > 0) {//...11
- cur_ll[j*n] |= 3;
- }
- else {//...10
- cur_ll[j*n] |= 2;
- cur_ll[j*n] &= ~1;
- }
- }
- }
- }
- }
- inline void fill(double *A, double *B, int n) {
- int i, j;
- for (i = 0; i < n; ++i, ++B, A += n) {
- for (j = i; j < n; ++j) {
- B[j*n] = A[j];
- }
- }
- }
- inline void mult_new(double *A, double *B, int n) {
- int i, j;
- bit_double cur;
- double *ptr = B + n - 1;
- double sin_fi, cos_fi;
- for (i = n - 1; i >= 0; --i, --ptr) {
- for (j = n - 1; j > i; --j) {
- cur.val = ptr[j*n];
- switch (cur.bits & 3) {
- case 0:
- cos_fi = cur.val;
- sin_fi = -sqrt(1. - cos_fi * cos_fi);
- break;
- case 1:
- cos_fi = cur.val;
- sin_fi = sqrt(1. - cos_fi * cos_fi);
- break;
- case 2:
- sin_fi = cur.val;
- cos_fi = -sqrt(1. - sin_fi * sin_fi);
- break;
- case 3:
- sin_fi = cur.val;
- cos_fi = sqrt(1. - sin_fi * sin_fi);
- break;
- }
- if (fabs(sin_fi) < eps)
- continue;
- mul_2(A, i, j, cos_fi, sin_fi, n);
- }
- }
- }
- inline void solve(ld tt) {
- //current stats, 4K x 4K: QRD - 55 sec, inv_U - 8 sec, mult_mat - 87 sec, cnt_residial - 65 sec, overall - 215 sec
- static double A[LEN * LEN], B[LEN *LEN];
- int n;
- double rs_1, rs_inf;
- cout << setprecision(4);// cout << fixed;
- cin >> n;
- gen(A, n, n);
- //input_mat(A, n, n, "");
- cout << "/*-----A------*/\n";
- print_mat(A, n, n);
- tt = clock();
- QRD_upg(A, n);
- cout << "Time: " << ((ld)clock() - tt) / CLOCKS_PER_SEC << endl;
- if (!inv_U(A, n)) {
- cout << "Matrix is non - invertible!\n";
- return;
- }
- cout << "Time: " << ((ld)clock() - tt) / CLOCKS_PER_SEC << endl;
- fill(A, B, n);
- mult_new(B, A, n);
- transp(B, n);
- cout << "/*-----A^(-1)------*/\n";
- print_mat(B, n, n);
- cout << "Time: " << ((ld)clock() - tt) / CLOCKS_PER_SEC << endl;
- gen(A, n, n);
- //input_mat(A, n, n, "");
- transp(A, n);
- residial_cnt(A, B, n, &rs_1, &rs_inf);
- cout << "residial = " << rs_1 << " for ||.||_1, " << rs_inf << " for ||.||_inf" << endl;
- }
- int main() {
- ld tt = clock();
- if (*infile != '\0')
- freopen(infile, "r", stdin);
- if (*outfile != '\0')
- freopen(outfile, "w", stdout);
- speedup;
- //coutdouble;
- //while(true)
- solve(tt);
- #ifdef LOCAL
- cout << "Time: " << ((ld)clock() - tt) / CLOCKS_PER_SEC << endl;
- while (true);
- #endif // LOCAL
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement