1195 - NMult
Enunț[edit | edit source]
Se consideră trei numere naturale nenule n, k și w.
Cerința[edit | edit source]
Să se scrie un program care determină numărul m al mulțimilor de forma {x[1], x[2], … ,x[k]} având ca elemente numere naturale nenule, ce satisfac simultan condițiile:
1 ≤ x[1] < x[2] < ... < x[k] ≤ n x[i+1] - x[i] ≥ w, 1 ≤ i ≤ k - 1
Date de intrare[edit | edit source]
Fișierul de intrare nmult.in conține pe prima linie trei numere naturale nenule n, k, w separate prin câte un spaţiu, cu semnificaţia de mai sus.
Date de ieșire[edit | edit source]
Fișierul de ieșire nmult.out va conține pe prima linie restul împărţirii numărului m la 666013.
Restricții și precizări[edit | edit source]
1 ≤ n, k, w ≤ 1.000.000;
Exemplu[edit | edit source]
Exemplu1[edit | edit source]
nmult.in <syntaxhighlight lang="python"> 5 2 2 </syntaxhighlight>
nmult.out <syntaxhighlight lang="python"> 6 </syntaxhighlight>
Exemplu2[edit | edit source]
nmult.in <syntaxhighlight lang="python"> 10 3 4 </syntaxhighlight>
nmult.out <syntaxhighlight lang="python"> 4 </syntaxhighlight>
Exemplu3[edit | edit source]
nmult.in <syntaxhighlight lang="python"> 10 4 4 </syntaxhighlight>
nmult.out <syntaxhighlight lang="python"> 0 </syntaxhighlight>
Rezolvare[edit | edit source]
<syntaxhighlight lang="python">
def validare(n, k, w):
if not(1 <= n <= 1000000 and 1 <= k <= 1000000 and 1 <= w <= 1000000): return False return True
def rezolvare(n, k, w):
MOD = 666013 # Cazul de bază if k == 1: return n
# Cazul în care diferența minimă între elemente este mai mare decât n if w >= n: return 0
# Aplicăm formula de recursivitate dp = [[0 for _ in range(k + 1)] for _ in range(n + 1)] for i in range(1, n + 1): dp[i][1] = 1 for j in range(2, k + 1): for i in range(1, n + 1): dp[i][j] = (dp[i - 1][j] + dp[max(0, i - w)][j - 1]) % MOD
# Suma soluțiilor pentru mulțimile de k elemente sol = 0 for i in range(1, n + 1): sol = (sol + dp[i][k]) % MOD
return sol
def main():
with open("nmult.in", "r") as fin: n, k, w = map(int, fin.readline().split())
if not validare(n, k, w): print("Date de intrare invalide") return
m = rezolvare(n, k, w)
with open("nmult.out", "w") as fout: fout.write(str(m) + "\n")
if __name__ == "__main__":
main()
</syntaxhighlight>
Explicații[edit | edit source]
Codul are trei funcții principale:
Funcția validare primește parametrii n, k și w și verifică dacă aceștia sunt în intervalul valid (între 1 și 1000000). Dacă parametrii nu sunt în intervalul valid, se returnează False, altfel se returnează True.
Funcția rezolvare primește parametrii n, k și w. În primul rând, se verifică cazurile speciale. Dacă k == 1, atunci numărul de mulțimi posibile este n. Dacă w >= n, atunci nu există nicio mulțime de k elemente cu diferența între oricare 2 termeni consecutivi mai mare sau egală cu w, așadar numărul de mulțimi posibile este 0.
În cazul general, se aplică formula de recursivitate pentru a calcula numărul de mulțimi posibile. Mai precis, se calculează matricea dp, unde dp[i][j] reprezintă numărul de mulțimi de j elemente care se termină cu numărul i și ale căror diferențe între oricare 2 termeni consecutivi sunt cel puțin w. Acest lucru se realizează cu ajutorul formulei: dp[i][j] = dp[i-1][j] + dp[max(0, i-w)][j-1].
În cele din urmă, se calculează suma soluțiilor pentru toate mulțimile de k elemente, care încep cu elementul 1 până la elementul n-w+1.
Funcția main citește datele de intrare din fișierul nmult.in și le validează cu ajutorul funcției validare. Apoi, calculează soluția problemei cu ajutorul funcției rezolvare și o scrie în fișierul nmult.out.