Pagini recente » Cod sursa (job #530636) | Cod sursa (job #2915010) | Cod sursa (job #357334) | Cod sursa (job #3276808) | Cod sursa (job #2937688)
#include <bits/stdc++.h>
using namespace std;
ifstream fin("sortari2.in");
ofstream fout("sortari2.out");
const int mod = 999017;
void addSelf(int &x, int y) {
x += y;
if (x >= mod) {
x -= mod;
}
}
void multSelf(int &x, int y) {
x = (int64_t)x * y % mod;
}
int mult(int x, int y) {
multSelf(x, y);
return x;
}
/*
(1) Numarul minim de swap-uri adiacente necesare pentru a sorta o permutare este egal cu cel
al inversiunilor.
(2) Numarul minim de swap-uri de orice fel necesare pentru a sorta o permutare este egal cu
n - numarul_de_cicluri_al_permutarii.
Prima valoare va fi mereu mai mare sau egala decat a doua pentru orice permutare(de fiecare data
cand fac un swap care imi creste cu 1 numarul de inversiuni, numarul de cicluri poate sa scada
cu maxim 1 si pentru permutarea identica(deja sortata) ambele valori sunt 0).
Astfel, pentru a numara cate permutari au valoarea (2) strict mai mica decat (1), pot sa scad din
numarul total de permutari(n!) cele care le au egale.
Conditia se poate rescrie ca numarul_de_inversiuni + numarul_de_cicluri = n.
Observatie: Pentru o permutare oarecare numarul_de_inversiuni + numarul_de_cicluri >= n(din (1) si (2)).
Observatie: n trebuie mereu sa se afle intr-un ciclu cu un sufix. Daca asta nu s-ar intampla,
numarul_de_inversiuni + numarul_de_cicluri ar fi > n(la un moment dat n ar adauga
o inversiune, dar nu ar scadea numarul de cicluri).
*/
/*
Exemplu:
1 2 3 | 4 5
1 2 3 | 5 4
1 2 | 3 4 5
1 2 | 5 3 4
1 2 | 3 4 5
1 2 | 4 5 3
*/
int main() {
int n;
fin >> n;
vector<int> cycles(n + 1);
// cycles[i] =def= numarul de cicluri de lungime i cu i - 1 inversiuni
cycles[1] = 1;
cycles[2] = 1;
for (int i = 3; i <= n; ++i) {
// Iau un ciclu de lungime mai mica si il inserez pe i unde trebuie pentru a forma numarul
// necesar de noi inversiuni.
// => cycles[i] = cycles[i - 1] + cycles[i - 2] + cycles[i - 3] + ... cycles[1]
// Se observa ca cycles[3] = cycles[1] + cycles[2]
// => cycles[4] = 2 * cycles[3]
// Inductiv se ajunge la cycles[i] = cycles[i - 1] * 2
cycles[i] = mult(cycles[i - 1], 2);
}
vector<int> dp(n + 1);
dp[0] = 1;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= i; ++j) {
// Fixez dimensiunea ciclului din care face parte i(care e cum am precizat anterior un sufix)
// si raman cu o permutare corecta de lungime i - j.
// Observatie: Numar solutii unice pentru ca mereu sufixele vor avea numar diferit de
// invsersiuni, deci vor fi diferite(vezi exemplu mai sus).
addSelf(dp[i], mult(dp[i - j], cycles[j]));
}
}
int res = 1;
for (int i = 1; i <= n; ++i) {
multSelf(res, i);
}
addSelf(res, mod - dp[n]);
fout << res << '\n';
fin.close();
fout.close();
return 0;
}