Java Laborator
Java Laborator
Note de Laborator
(uz intern - draft v1)
Adrian Rabaea
Cuprins
1 Exercit ii simple 1
1.1 Algoritmi elementari . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 Acest num ar este prim? . . . . . . . . . . . . . . . . . . . . 1
1.1.2 Lista numerelor prime . . . . . . . . . . . . . . . . . . . . . 2
1.1.3 Descompunere n factori primi . . . . . . . . . . . . . . . . 2
1.1.4 Cel mai mare divizor comun . . . . . . . . . . . . . . . . . . 3
1.1.5 Cel mai mic multiplu comun . . . . . . . . . . . . . . . . . 4
1.1.6 Cel mai mic multiplu comun, optimizat . . . . . . . . . . . 5
1.1.7 Calculul puterilor . . . . . . . . . . . . . . . . . . . . . . . . 7
1.1.8 Calculul puterilor, optimizat . . . . . . . . . . . . . . . . . 7
1.1.9 Calculul factorialului . . . . . . . . . . . . . . . . . . . . . . 8
1.1.10 Calculul combin arilor . . . . . . . . . . . . . . . . . . . . . 8
1.1.11 Numarul lui Catalan C
n
=
1
n+1
C
n
2n
. . . . . . . . . . . . . . 10
1.1.12 Produsul a dou a polinoame . . . . . . . . . . . . . . . . . . 11
1.1.13 Schema lui Horner . . . . . . . . . . . . . . . . . . . . . . . 12
1.1.14 Calculul valorii unui polinom . . . . . . . . . . . . . . . . . 13
1.1.15 Puterea unui polinom . . . . . . . . . . . . . . . . . . . . . 13
1.1.16 Derivata unui polinom . . . . . . . . . . . . . . . . . . . . . 14
1.1.17 Derivata de ordinul k a unui polinom . . . . . . . . . . . . . 15
1.1.18 Derivata de ordinul k a funct iei f(x) = P
n
(x)e
x
. . . . . . 16
1.1.19 Ordinul unei permutari . . . . . . . . . . . . . . . . . . . . 17
1.1.20 Suma puterilor r adacinilor ecuat iei de grad 2 . . . . . . . . 19
1.1.21 Suma puterilor r adacinilor ecuat iei de grad 3 . . . . . . . . 19
1.1.22 Sirul lui Fibonacci si proport ia de aur . . . . . . . . . . . 20
1.1.23 Descompunere Fibonacci . . . . . . . . . . . . . . . . . . . 21
1.1.24 Numarul permutarilor idempotente . . . . . . . . . . . . . . 22
1.1.25 Fract ie continua: determinarea coecient ilor . . . . . . . . . 22
1.1.26 Fract ie continua: determinarea fract iei init iale . . . . . . . . 23
1.1.27 Generare polinom cu r adacini fract ionare date . . . . . . . 24
1.1.28 Radacini rat ionale . . . . . . . . . . . . . . . . . . . . . . . 25
1.1.29 Numarul divizorilor unui num ar natural . . . . . . . . . . . 26
1.1.30 Funct ia lui Euler . . . . . . . . . . . . . . . . . . . . . . . . 27
iii
1.1.31 Formula de calcul pentru funct ia lui Euler . . . . . . . . . . 28
1.1.32 Ghiceste num arul . . . . . . . . . . . . . . . . . . . . . . . . 28
1.1.33 Calculul funct iei arcsin . . . . . . . . . . . . . . . . . . . . . 30
1.1.34 Algoritmul lui Euclid extins . . . . . . . . . . . . . . . . . . 31
1.2 Calculul unor sume si produse . . . . . . . . . . . . . . . . . . . . . 32
1.2.1 Calculul funct iei arcsin . . . . . . . . . . . . . . . . . . . . . 32
1.2.2 Calcul f(n) =
n
k=0
1
2
k
C
n
n+k
. . . . . . . . . . . . . . . . . 33
1.2.3 Calcul f(n) =
n1
k=0
C
k
n1
n
n1k
(k + 1)! . . . . . . . . . . 34
1.2.4 Calcul f(n) = n
n1
+
n1
k=1
C
k
n
k
k1
(n k)
nk
. . . . . . . 35
1.2.5 Calcul f(n) = n!
_
1
1
1!
+
1
2!
... +
(1)
n
n!
_
. . . . . . . . . 37
1.2.6 Calcul s(n, m) =
m1
k=0
C
k
m
(1)
k
(mk)
n
. . . . . . . . . . 37
1.2.7 Calcul f(m, n,
1
, ...,
n
) =
_
C
1
m
_
1
...
_
C
n
m+n1
_
n
. . . . . 39
1.2.8 Calcul f(...) =
m
k=1
(1)
mk
_
C
k
m
_ _
C
1
k
_
1
...
_
C
n
k+n1
_
n
. 40
1.2.9 Calcul f(n) =
1
2
n
n
k=0
(1)
k
C
k
n
2
k
(2n k)! . . . . . . . . . 42
1.2.10 Numerele Stirling de spet a a II-a . . . . . . . . . . . . . . . 43
1.2.11 Numerele lui Bell . . . . . . . . . . . . . . . . . . . . . . . . 44
1.2.12 Partit iile unui num ar natural . . . . . . . . . . . . . . . . . 45
1.2.13 Recurent a Catalan: C
n
=
n
k=1
C
k1
C
nk
unde C
0
= 1 . . 46
1.2.14 Recurent a: E
n
= E
2
E
n1
+ E
3
E
n2
+ ... + E
n1
E
2
unde
E
1
= E
2
= 1 . . . . . . . . . . . . . . . . . . . . . . . . . . 47
1.2.15 Numerele Stirling de spet a a II-a . . . . . . . . . . . . . . . 48
1.2.16 Calcul f(n) =
n
k=0
C
k
n
F
k
. . . . . . . . . . . . . . . . . . . 50
1.2.17 Calcul f(n) =
n
k=0
C
k
n
2
k
F
k
. . . . . . . . . . . . . . . . . 51
2 Simularea operat iilor cu numere mari 53
2.1 Operat ii cu numere mari . . . . . . . . . . . . . . . . . . . . . . . . 53
2.1.1 Vectorul cifrelor unui num ar . . . . . . . . . . . . . . . . . . 53
2.1.2 Adunarea numerelor mari . . . . . . . . . . . . . . . . . . . 54
2.1.3
Inmult irea numerelor mari . . . . . . . . . . . . . . . . . . . 55
2.1.4
Imp art irea numerelor mari la 2 . . . . . . . . . . . . . . . . 57
2.1.5 Funct ia putere cu numere mari . . . . . . . . . . . . . . . . 59
2.1.6 Funct ia factorial cu numere mari . . . . . . . . . . . . . . . 61
2.1.7 Calculul combin arilor cu numere mari . . . . . . . . . . . . 63
2.2 Sume si produse cu numere mari . . . . . . . . . . . . . . . . . . . 66
2.2.1 Numarul lui Catalan C
n
=
1
n+1
C
n
2n
cu numere mari . . . . 66
2.2.2 Calcul f(n) =
n
k=0
1
2
k
C
n
n+k
cu numere mari . . . . . . . . 68
2.2.3 Calcul f(n) =
n1
k=0
C
k
n1
n
n1k
(k + 1)! cu numere mari . 72
2.2.4 Calcul f(n) = n
n1
+
n1
k=1
C
k
n
k
k1
(n k)
nk
cu numere
mari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
2.2.5 Calcul f(m, n,
1
, ...,
n
) =
_
C
1
m
_
1
...
_
C
n
m+n1
_
n
cu nu-
mere mari . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
2.2.6 Numerele Stirling de spet a a II-a cu numere mari . . . . . . 82
2.2.7 Numerele lui Bell cu numere mari . . . . . . . . . . . . . . 84
2.2.8 Partit iile unui num ar natural cu numere mari . . . . . . . . 88
2.2.9 Recurent a Catalan C
n
=
n
k=1
C
k1
C
nk
unde C
0
= 1, cu
numere mari . . . . . . . . . . . . . . . . . . . . . . . . . . 90
2.2.10 Recurent a: E
n
= E
2
E
n1
+ E
3
E
n2
+ ... + E
n1
E
2
unde
E
1
= E
2
= 1 cu numere mari . . . . . . . . . . . . . . . . . 93
2.2.11 Calcul f(n) =
n
k=0
C
k
n
F
k
cu numere mari . . . . . . . . . 96
2.2.12 Calcul f(n) =
n
k=0
C
k
n
2
k
F
k
cu numere mari . . . . . . . . 99
2.2.13 Fract ie continua: determinarea fract iei init iale cu numere mari103
2.2.14 Numarul permutarilor idempotente, cu numere mari . . . . 105
3 OJI 2002 clasa a IX-a 109
3.1 Poarta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
3.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 110
3.1.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 110
3.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 110
3.2 Mouse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
3.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 113
3.2.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 113
3.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 113
4 OJI 2003 clasa a IX-a 117
4.1 Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
4.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 118
4.1.2 Rezolvare detaliat a * . . . . . . . . . . . . . . . . . . . . . . 119
4.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 119
4.2 Numere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
4.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 122
4.2.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 122
4.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 122
5 OJI 2004 clasa a IX-a 125
5.1 Expresie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
5.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 126
5.1.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 127
5.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 127
5.2 Reactivi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
5.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 133
5.2.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 134
5.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 134
6 OJI 2005 clasa a IX-a 137
6.1 Numere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
6.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 138
6.1.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 138
6.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 138
6.2 MaxD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
6.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 140
6.2.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 141
6.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 141
7 OJI 2006 clasa a IX-a 145
7.1 Flori . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
7.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 146
7.1.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 147
7.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 147
7.2 Pluton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
7.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 151
7.2.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 152
7.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 152
8 OJI 2007 clasa a IX-a 157
8.1 Cartele - OJI 2007 . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
8.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 158
8.1.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 159
8.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 159
8.2 Paritate - OJI 2007 . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
8.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 167
8.2.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 168
8.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 168
9 ONI 2000 clasa a IX-a 171
9.1 Algoritm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
9.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 174
9.1.2 Rezolvare detaliat a * . . . . . . . . . . . . . . . . . . . . . . 174
9.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 176
9.2 Cod de identicare . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
9.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 179
9.2.2 Rezolvare detaliat a * . . . . . . . . . . . . . . . . . . . . . . 179
9.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 182
9.3 Comoara . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
9.3.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 184
9.3.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 185
9.3.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 185
9.4 Cuburi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
9.4.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 189
9.4.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 189
9.4.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 189
9.5 Fibo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
9.5.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 192
9.5.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 192
9.5.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 192
9.6 Kommando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
9.6.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 197
9.6.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 197
9.6.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 197
10 ONI 2001 clasa a IX-a 209
10.1 Ferma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
10.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 211
10.1.2 Rezolvare detaliat a * . . . . . . . . . . . . . . . . . . . . . . 211
10.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 212
10.2 Fract ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
10.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 215
10.2.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 215
10.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 215
10.3 Tablou . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 216
10.3.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 217
10.3.2 Rezolvare detaliat a * . . . . . . . . . . . . . . . . . . . . . . 217
10.3.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 219
10.4 Competit ie dicila . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
10.4.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 221
10.4.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 221
10.4.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 221
10.5 Cuvinte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
10.5.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 223
10.5.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 224
10.5.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 224
10.6 Grup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
10.6.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 227
10.6.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 227
10.6.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 227
11 ONI 2002 clasa a IX-a 231
11.1 Pentagon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 231
11.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 232
11.1.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 233
11.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 233
11.2 Pod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234
11.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 236
11.2.2 Rezolvare detaliat a * . . . . . . . . . . . . . . . . . . . . . . 237
11.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 242
11.3 Suma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
11.3.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 246
11.3.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 247
11.3.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 247
11.4 Becuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
11.4.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 249
11.4.2 Rezolvare detaliat a * . . . . . . . . . . . . . . . . . . . . . . 250
11.4.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 255
11.5 Discuri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
11.5.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 259
11.5.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 260
11.5.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 260
11.6 Cod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
11.6.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 263
11.6.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 264
11.6.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 264
12 ONI 2003 clasa a IX-a 267
12.1 Seti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
12.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 268
12.1.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 268
12.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 269
12.2 Scaune . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 272
12.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 273
12.2.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 274
12.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 274
12.3 Circular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278
12.3.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 278
12.3.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 279
12.3.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 280
12.4 Criptare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 282
12.4.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 284
12.4.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 284
12.4.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 286
12.5 Masina . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
12.5.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 288
12.5.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 289
12.5.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 289
12.6 Operat ii . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
12.6.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 291
12.6.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 292
12.6.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 292
13 ONI 2004 clasa a IX-a 295
13.1 Coduri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
13.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 296
13.1.2 Rezolvare detaliat a * . . . . . . . . . . . . . . . . . . . . . . 296
13.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 297
13.2 Logic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
13.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 299
13.2.2 Rezolvare detaliat a * . . . . . . . . . . . . . . . . . . . . . . 299
13.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 303
13.3 Poligon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 305
13.3.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 307
13.3.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . 307
13.3.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 307
13.4 Sablon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 311
13.4.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 312
13.4.2 Rezolvare detaliat a * . . . . . . . . . . . . . . . . . . . . . . 313
13.4.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 314
13.5 Sir . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 316
13.5.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 316
13.5.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 317
13.5.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 317
13.6 Snipers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 317
13.6.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 319
13.6.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 319
13.6.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 319
14 ONI 2005 clasa a IX-a 323
14.1 Bifo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 323
14.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 325
14.1.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 325
14.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 327
14.2 Romeo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 333
14.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 335
14.2.2 Rezolvare detaliat a * . . . . . . . . . . . . . . . . . . . . . . 338
14.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 338
14.3 Seceta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 338
14.3.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 340
14.3.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 340
14.3.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 340
14.4 Biblos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 352
14.4.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 353
14.4.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 354
14.4.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 354
14.5 Joc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 357
14.5.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 359
14.5.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 360
14.5.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 360
14.6 Pal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 366
14.6.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 368
14.6.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 368
14.6.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 368
15 ONI 2006 clasa a IX-a 373
15.1 Factorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 373
15.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 374
15.1.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 375
15.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 375
15.2 Limbaj . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 376
15.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 378
15.2.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 378
15.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 378
15.3 Panouri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 385
15.3.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 386
15.3.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 387
15.3.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 387
15.4 Peret i . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 390
15.4.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 392
15.4.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 392
15.4.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 392
15.5 Sant . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394
15.5.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 396
15.5.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 396
15.5.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 396
15.6 Zumzi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 398
15.6.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 400
15.6.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 401
15.6.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 402
16 ONI 2007 clasa a IX-a 411
16.1 Agitat ie - ONI 2007 . . . . . . . . . . . . . . . . . . . . . . . . . . 411
16.1.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 413
16.1.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 414
16.1.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 414
16.2 Coduri - ONI 2007 . . . . . . . . . . . . . . . . . . . . . . . . . . . 415
16.2.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 417
16.2.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 417
xi
16.2.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 417
16.3 Lacuri - ONI 2007 . . . . . . . . . . . . . . . . . . . . . . . . . . . 421
16.3.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 423
16.3.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 424
16.3.3 Codul sursa *! . . . . . . . . . . . . . . . . . . . . . . . . . 424
16.4 Secv - ONI 2007 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 427
16.4.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 428
16.4.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 429
16.4.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 429
16.5 Sotron - ONI 2007 . . . . . . . . . . . . . . . . . . . . . . . . . . . 431
16.5.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 432
16.5.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 433
16.5.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 433
16.6 Triunghi - ONI 2007 . . . . . . . . . . . . . . . . . . . . . . . . . . 435
16.6.1 Indicat ii de rezolvare - descriere solut ie * . . . . . . . . . . 436
16.6.2 Rezolvare detaliat a . . . . . . . . . . . . . . . . . . . . . . . 437
16.6.3 Codul sursa * . . . . . . . . . . . . . . . . . . . . . . . . . . 437
xii
Capitolul 1
Exercit ii simple
1.1 Algoritmi elementari
1.1.1 Acest numar este prim?
import java.io.*;
class nrPrim {
public static void main (String[]args) throws IOException {
long x;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("x = "); x=Long.parseLong(br.readLine());
if(estePrim(x)) System.out.println(x+" este PRIM");
else System.out.println(x+" NU este PRIM");
}
static boolean estePrim(long nr) {
if((nr==0)||(nr==1)) return false;
if((nr==2)||(nr==3)) return true;
if(nr%2==0) return false;
long d=3;
while((nr%d!=0)&&(d*d<=nr)) d=d+2;
if(nr%d==0) return false; else return true;
}
}
1
2 CAPITOLUL 1. EXERCIT II SIMPLE
1.1.2 Lista numerelor prime
import java.io.*;
class NumerePrimeLista
{
public static void main(String[]args)throws IOException
{
BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in));
int n;
System.out.println("Dim. lista:"); n=Integer.parseInt(stdin.readLine());
int[] prim=new int[n];
prim[0]=2;
prim[1]=3;
int k=1; // pozitia in lista a ultimului numar prim plasat
int nr=5; // nr este urmatorul numar prim ?
int j,primj;// parcurg lista
while(k<=n-2)
{
j=0;
primj=prim[j];
while((primj*primj<=nr)&&(nr%primj!=0)) primj=prim[++j];
if(primj*primj>nr) prim[++k]=nr;
nr=nr+2;
}
for(k=0;k<n;k++) System.out.println(k+ " : "+prim[k]);
}
}
1.1.3 Descompunere n factori primi
import java.io.*;
class DescFactori
{
public static void main (String[]args) throws IOException
{
long x;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("x = "); x=Long.parseLong(br.readLine());
System.out.print("x = "); descFact(x);
}
1.1. ALGORITMI ELEMENTARI 3
static void descFact(long nr)
{
long d=2;
if((nr==0)||(nr==1))
{
System.out.println(nr);
return;
}
while(nr%d==0)
{
System.out.print(d+" ");
nr=nr/d;
}
d=3;
while((d*d<=nr)&&(nr!=1))
{
while(nr%d==0)
{
System.out.print(d+" ");
nr=nr/d;
}
d=d+2;
}
if(nr!=1) System.out.println(nr);
else System.out.println();
}
}// class
1.1.4 Cel mai mare divizor comun
import java.io.*;
class Cmmdc
{
public static void main (String[]args) throws IOException
{
long x,y;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("x = "); x=Long.parseLong(br.readLine());
System.out.print("y = "); y=Long.parseLong(br.readLine());
System.out.println("cmmdc("+x+","+y+") = "+cmmdc(x,y));
4 CAPITOLUL 1. EXERCIT II SIMPLE
}
static long cmmdc(long a, long b)
{
long d,i,c,r;
if (a>b) {d=a; i=b;} else {d=b; i=a;}
while (i != 0)
{
c=d/i; // nu se foloseste !
r=d%i;
d=i;
i=r;
}
return d;
}
}
1.1.5 Cel mai mic multiplu comun
import java.io.*;
class Cmmmc1
{
public static void main (String[]args) throws IOException
{
long x,y;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("x = "); x=Long.parseLong(br.readLine());
System.out.print("y = "); y=Long.parseLong(br.readLine());
System.out.println("cmmmc("+x+","+y+") = "+cmmmc(x,y));
}
static long cmmmc(long a, long b)
{
int d;
int nrda,nrdb;
long p,pa,pb;
p=1;
d=2;
nrda=0; pa=1;
while(a%d==0) { nrda++; pa=pa*d; a=a/d;}
1.1. ALGORITMI ELEMENTARI 5
nrdb=0; pb=1;
while(b%d==0) { nrdb++; pb=pb*d; b=b/d;}
if(pa+pb>0)
if(pa>pb) p=p*pa; else p=p*pb;
d=3;
while((d*d<=a)||(d*d<=b)) // se poate optimiza aici?
{
nrda=0; pa=1;
while(a%d==0) { nrda++; pa=pa*d; a=a/d; }
nrdb=0; pb=1;
while(b%d==0) { nrdb++; pb=pb*d; b=b/d; }
if(pa+pb>0)
if(pa>pb) p=p*pa; else p=p*pb;
d=d+2;
}
System.out.println("p="+p+" si A RAMAS a="+a+" b="+b);
if(a==b) p=p*a; // ex: a=2*17 b=3*17
else p=p*a*b; // ex: a=2*3 b=2*5
return p;
}
}
1.1.6 Cel mai mic multiplu comun, optimizat
import java.io.*;
class Cmmmc2
{
public static void main (String[]args) throws IOException
{
long x,y;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("x = "); x=Long.parseLong(br.readLine());
System.out.print("y = "); y=Long.parseLong(br.readLine());
// x=2*2*2;
// y=2*3*3*3*3;
System.out.println("cmmmc("+x+","+y+") = "+cmmmc(x,y));
}
static long cmmmc(long a, long b)
{
6 CAPITOLUL 1. EXERCIT II SIMPLE
int d;
int nrda,nrdb;
long p,pa,pb,maxab, minab;
p=1;
d=2;
nrda=0; pa=1;
while(a%d==0) { nrda++; pa=pa*d; a=a/d;}
nrdb=0; pb=1;
while(b%d==0) { nrdb++; pb=pb*d; b=b/d;}
if(pa+pb>0)
if(pa>pb) p=p*pa; else p=p*pb;
d=3;
while((d*d<=a)&&(d*d<=b)) // cel putin unul poate sa ramana numar prim!
{
nrda=0; pa=1;
while(a%d==0) { nrda++; pa=pa*d; a=a/d;}
nrdb=0; pb=1;
while(b%d==0) { nrdb++; pb=pb*d; b=b/d;}
if(pa+pb>0)
if(pa>pb) p=p*pa; else p=p*pb;
d=d+2;// ex: a=2*3 b=2*9 ???
}
// System.out.println("Ultimul divizor incercat este d="+max(2,(d-2)));
// System.out.println("p="+p+" si A RAMAS a="+a+" b="+b);
maxab=max(a,b);
minab=min(a,b);
if(maxab>1) // a ramas ceva in a sau b
if(a==b) p=p*a; // ex: a=2*17 b=3*17
else if(maxab%minab!=0) p=p*a*b; // ex: a=2*3 b=2*5
else// ex: a=2*3 b=2*9
{
p=p*minab;
a=a/minab;
b=b/minab;
p=p*a*b; // cel mai mic este 1
}
return p;
}
static long max(long a, long b) { if(a>b) return a; else return b; }
static long min(long a, long b) { if(a<b) return a; else return b; }
}
1.1. ALGORITMI ELEMENTARI 7
1.1.7 Calculul puterilor
import java.io.*;
class Putere
{
public static void main (String[]args) throws IOException
{
int a,n;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("a = "); a=Integer.parseInt(br.readLine());
System.out.print("n = "); n=Integer.parseInt(br.readLine());
System.out.println("putere("+a+","+n+") = "+putere(a,n));
}
static long putere(int a,int n)
{
int k;
long p;
p=1;
for(k=1;k<=n;k++) p=p*a;
return p;
}
}
1.1.8 Calculul puterilor, optimizat
import java.io.*;
class PutereOptimizat
{
public static void main (String[]args) throws IOException
{
int a,n;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("a = "); a=Integer.parseInt(br.readLine());
System.out.print("n = "); n=Integer.parseInt(br.readLine());
System.out.println("putere("+a+","+n+") = "+putere(a,n));
}
static long putere(int a,int n)
8 CAPITOLUL 1. EXERCIT II SIMPLE
{
int k;
long p, a2k;
p=1;
a2k=a;
while(n!=0)
{
if(n%2==1) p=p*a2k;
a2k=a2k*a2k;
n=n/2;
}
return p;
}
}
1.1.9 Calculul factorialului
import java.io.*;
class Factorial
{
public static void main (String[]args) throws IOException
{
int n;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("n = "); n=Integer.parseInt(br.readLine());
System.out.println(n+"! = "+factorial(n));
}
static long factorial(int n)
{
int k;
long p;
p=1;
for(k=1;k<=n;k++) p=p*k;
return p;
}
}
1.1.10 Calculul combinarilor
1.1. ALGORITMI ELEMENTARI 9
import java.io.*;
class Combinari
{
public static void main (String[]args) throws IOException
{
int n,k;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("n = "); n=Integer.parseInt(br.readLine());
System.out.print("k = "); k=Integer.parseInt(br.readLine());
System.out.println("combinari("+n+","+k+") = "+comb(n,k));
}
static long comb(int n,int k)
{
int i,j,d;
if(k>n/2) k=n-k; // o mica optimizare !
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(x[i],y[j]);
x[i]=x[i]/d;
y[j]=y[j]/d;
if(y[j]==1) break;
}
long p=1;
for(i=1;i<=k;i++) p=p*x[i];
return p;
}
static int cmmdc(int a, int b)
{
int d,i,c,r;
if(a>b) {d=a; i=b;} else {d=b; i=a;}
while (i != 0)
{
c=d/i; // nu se foloseste !
r=d%i;
d=i;
i=r;
10 CAPITOLUL 1. EXERCIT II SIMPLE
}
return d;
}
}
1.1.11 Numarul lui Catalan C
n
=
1
n+1
C
n
2n
import java.io.*;
class Catalan
{
public static void main (String[]args) throws IOException
{
int n,k;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("n = "); n=Integer.parseInt(br.readLine());
System.out.println("catalan("+n+") = "+catalan(n));
}
static long catalan(int n)
{
int i,j,d;
int[] x=new int[n+1];
int[] y=new int[n+1];
for(i=2;i<=n;i++) x[i]=n+i;
for(j=2;j<=n;j++) y[j]=j;
for(j=2;j<=n;j++)
for(i=2;i<=n;i++)
{
d=cmmdc(x[i],y[j]);
x[i]=x[i]/d;
y[j]=y[j]/d;
if(y[j]==1) break;
}
long p=1;
for(i=2;i<=k;i++) p=p*x[i];
return p;
}
static int cmmdc(int a, int b)
{
int d,i,c,r;
1.1. ALGORITMI ELEMENTARI 11
if(a>b) {d=a; i=b;} else {d=b; i=a;}
while (i != 0)
{
c=d/i; // nu se foloseste !
r=d%i;
d=i;
i=r;
}
return d;
}
}
1.1.12 Produsul a doua polinoame
class ProdusPolinoame
{
public static void main(String[] args)
{
int gradp=1;
int gradq=2;
int[] p=new int[gradp+1];
int[] q=new int[gradq+1];
p[gradp]=1;
p[0]=1;
afisv("p = ",p);
q[gradq]=1;
q[1]=2;
q[0]=1;
afisv("q = ",q);
int[] pq=prodPol(p,q);
afisv("p * q = ",pq);
}
static int[] prodPol(int[] a, int[] b)
{
int i,j;
int na=a.length-1;
int nb=b.length-1;
int nc=na+nb;
12 CAPITOLUL 1. EXERCIT II SIMPLE
int[] c=new int[nc+1];
for(i=0;i<=na;i++)
for(j=0;j<=nb;j++)
c[i+j]=c[i+j]+a[i]*b[j];
return c;
}
static void afisv(String s, int[] x)
{
int n=x.length-1;
int i;
System.out.print(s+" ");
for(i=n;i>=0;i--) System.out.print(x[i]+" ");
System.out.println();
}
}
1.1.13 Schema lui Horner
import java.io.*; // impart p(X) la X-a si obtin catul=q(X) restul=r
class Horner
{
public static void main(String[] args) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.print("Gradul polinomului P(X): ");
int n=Integer.parseInt(br.readLine());
int[] p=new int[n+1];
for(int i=n;i>=0;i--)
{
System.out.print("p["+i+"]=");
p[i]=Integer.parseInt(br.readLine());
}
System.out.print("a = ");
int a=Integer.parseInt(br.readLine());
int[] q=new int[n+1];
q[n]=p[n];
for(int k=n-1;k>=0;k--) q[k]=q[k+1]*a+p[k];
for(int k=n;k>0;k--) System.out.print(q[k]+" ");
System.out.println("\n"+"r="+q[0]);
1.1. ALGORITMI ELEMENTARI 13
}// main
}// class
1.1.14 Calculul valorii unui polinom
import java.io.*; // in schema lui Horner restul=r=p(a)
class ValoarePolinom
{
public static void main(String[] args) throws IOException
{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.print("Gradul polinomului P(X): ");
int n=Integer.parseInt(br.readLine());
int[] p=new int[n+1];
for(int i=n;i>=0;i--)
{
System.out.print("p["+i+"]=");
p[i]=Integer.parseInt(br.readLine());
}
System.out.print("a = ");
int a=Integer.parseInt(br.readLine());
int r=p[n];
for(int k=n-1;k>=0;k--) r=r*a+p[k];
System.out.println("p("+a+")="+r);
}
}
1.1.15 Puterea unui polinom
class PuterePolinom
{
public static void main(String[] args)
{
int gradp=1; // gradul polinomului p
int m=15; // puterea la care se ridica polinomul p
int k;
int[] p=new int[gradp+1];
int[] pk={1};
p[gradp]=1;
14 CAPITOLUL 1. EXERCIT II SIMPLE
p[0]=1;
afisv("p^"+0+" = ",pk);
for(k=1;k<=m;k++)
{
pk=prodPol(pk,p);
afisv("p^"+k+" = ",pk);
}
}
static int[] prodPol(int[] a, int[] b)
{
int i,j;
int na=a.length-1;
int nb=b.length-1;
int nc=na+nb;
int[] c=new int[nc+1];
for(i=0;i<=na;i++)
for(j=0;j<=nb;j++)
c[i+j]=c[i+j]+a[i]*b[j];
return c;
}
static void afisv(String s, int[] x)
{
int n=x.length-1;
int i;
System.out.print(s+" ");
for(i=n;i>=0;i--) System.out.print(x[i]+" ");
System.out.println();
}
}
1.1.16 Derivata unui polinom
class DerivataPolinom
{
public static void main(String[] args)
{
int gradp=3; // gradul polinomului p
int[] p=new int[gradp+1];
1.1. ALGORITMI ELEMENTARI 15
p[gradp]=2;
p[2]=3;
p[1]=4;
p[0]=5;
afisv("p = ",p);
afisv("p = ",derivPol(p));
}
static int[] derivPol(int[] a)
{
int i,j;
int na=a.length-1; // gradul polinomului
int nb=na-1; // gradul derivatei
int[] b=new int[nb+1];
for(i=1;i<=na;i++)
b[i-1]=i*a[i];
return b;
}
static void afisv(String s, int[] x)
{
int n=x.length-1;
int i;
System.out.print(s+" ");
for(i=n;i>=0;i--) System.out.print(x[i]+" ");
System.out.println();
}
}
1.1.17 Derivata de ordinul k a unui polinom
class Derivata_kPolinom
{
public static void main(String[] args)
{
int gradp=3; // gradul polinomului p
int[] p=new int[gradp+1];
int k=3; // ordinul derivatei
p[gradp]=2;
p[2]=3;
p[1]=4;
16 CAPITOLUL 1. EXERCIT II SIMPLE
p[0]=5;
afisv("p = ",p);
int[] pk=p;
afisv("p^("+0+") = ",pk);
for(int i=1;i<=k;i++)
{
pk=derivPol(pk); // polinomul p se distruge !
afisv("p^("+i+") = ",pk);
}
}
static int[] derivPol(int[] a)
{
int i,j;
int na=a.length-1; // gradul polinomului
int nb=na-1; // gradul derivatei
int[] b=new int[nb+1];
for(i=1;i<=na;i++)
b[i-1]=i*a[i];
return b;
}
static void afisv(String s, int[] x)
{
int n=x.length-1;
int i;
System.out.print(s+" ");
for(i=n;i>=0;i--) System.out.print(x[i]+" ");
System.out.println();
}
}
1.1.18 Derivata de ordinul k a funct iei f(x) = P
n
(x)e
x
class DerivataPolExp
{
public static void main(String[] args)
{
int alfa=1;
int gradp=1; // gradul polinomului p
long[] p=new long[gradp+1];
int k=9; // ordinul derivatei
1.1. ALGORITMI ELEMENTARI 17
p[gradp]=1;
p[0]=0;
afisv("p = ",p);
long[] pk=p;
afisv("f^("+0+") ==> q = ",pk);
for(int i=1;i<=k;i++)
{
pk=deriv(pk,alfa); // polinomul p se distruge !
afisv("f^("+i+") ==> q = ",pk);
}
}
static long[] deriv(long[] a,int alfa)
{
int n=a.length-1;
long[] b=new long[n+1];
int k;
b[n]=a[n]*alfa;
for(k=0;k<=n-1;k++) b[k]=(k+1)*a[k+1]+a[k]*alfa;
return b;
}
static void afisv(String s, long[] x)
{
int n=x.length-1;
int i;
System.out.print(s+" ");
for(i=n;i>=0;i--) System.out.print(x[i]+" ");
System.out.println();
}
}
1.1.19 Ordinul unei permutari
import java.io.*;
class OrdinPermutare
{
static int n;
static int[] pr;
static int[] p;
public static void main(String[] args) throws IOException
18 CAPITOLUL 1. EXERCIT II SIMPLE
{
int r,i;
StreamTokenizer st = new StreamTokenizer(new BufferedReader(
new FileReader("permutare.in")));
PrintWriter out = new PrintWriter(new BufferedWriter(
new FileWriter("permutare.out")));
st.nextToken();n=(int)st.nval;
p=new int[n+1];
pr=new int[n+1];
for(i=1;i<=n;i++)
{
st.nextToken(); p[i]=(int)st.nval;
}
r=1;
for(i=1;i<=n;i++) pr[i]=p[i];
while(!pidentica(pr))
{
r++;
pr=inmp(pr,p);
}
out.println(r);
out.close();
}
static int[] inmp(int[]a,int[]b)
{
int k;
int[] c=new int[n+1];
for(k=1;k<=n;k++) c[k]=a[b[k]];
return c;
}
static boolean pidentica(int[]p)
{
int i;
boolean ok=true;
for(i=1;i<=n;i++)
if(p[i]!=i)
{
ok=false;
break;
1.1. ALGORITMI ELEMENTARI 19
}
return ok;
}
}
1.1.20 Suma puterilor radacinilor ecuat iei de grad 2
class SnEc2
{
public static void main(String[] args)
{
int a,b,c;
int n=10;
int s,p;
a=1;
b=1;
c=2; // 1 1 2 ==> x^2 + x + 1 = 0
s=-b/a;
p=c/a;
long[] ss=new long[n+1];
ss[1]=s;
ss[2]=s*s-2*p;
int k;
for(k=3;k<=n;k++) ss[k]=s*ss[k-1]-p*ss[k-2];
for(k=1;k<=n;k++) System.out.println(k+" : "+ss[k]);
}
}
1.1.21 Suma puterilor radacinilor ecuat iei de grad 3
class SnEc3
{
public static void main(String[]args)
{
int a,b,c,d;
long s1,s2,s3;
int n=23;
long[] s=new long[n+1];
int k;
a=1;
b=-6;
20 CAPITOLUL 1. EXERCIT II SIMPLE
c=11;
d=-6; // ==> x^3-6x^2+11x-6=0 ==> 1, 2, 3
s1=-b/a;
s2=c/a;
s3=-d/a;
s[0]=3;
s[1]=s1;
s[2]=s1*s1-2*s2;
System.out.println("s1="+s1+" s2="+s2+" s3="+s3);
for(k=3;k<=n;k++) s[k]=s1*s[k-1]-s2*s[k-2]+s3*s[k-3];
for(k=0;k<=n;k++) System.out.println(k+" : "+s[k]);
System.out.println(" "+Long.MAX_VALUE+" = Long.MAX_VALUE");
}
}
1.1.22 Sirul lui Fibonacci si proport ia de aur
import java.io.*;
class SirFibonacci
{
public static void main (String[]args) throws IOException
{
int k,n;
long[] f;
double[] r;
double[] e;
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.print("n = "); n=Integer.parseInt(br.readLine());
f=new long[n+1];
r=new double[n+1];
e=new double[n+1];
f[0]=0;
f[1]=1;
for(k=2;k<=n;k++) f[k]=f[k-1]+f[k-2];
for(k=2;k<=n;k++) r[k]=(double)f[k]/f[k-1];
for(k=2;k<=n;k++) e[k]=r[k]-(1+Math.sqrt(5))/2;
for(k=2;k<=n;k++)
System.out.println(k+" : "+f[k]+"\t "+r[k]+"\t "+e[k]);
}
1.1. ALGORITMI ELEMENTARI 21
}
1.1.23 Descompunere Fibonacci
import java.io.*;
class DescompunereFibonacci
{
static int n=92; // cel mai mare numar Fibonacci care incape pe LONG!
static long[] f=new long[n+1];
public static void main (String[]args) throws IOException
{
long x; // x=1234567890123456789L; cel mult!
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
System.out.print("x = ");
x=Long.parseLong(br.readLine());
long y;
int iy;
int k;
int nrt=0;
f[0]=0;
f[1]=1;
f[2]=1;
for(k=3;k<=n;k++) f[k]=f[k-1]+f[k-2];
for(k=0;k<=n;k++) System.out.println(k+" : "+f[k]);
System.out.println(" "+Long.MAX_VALUE+" = Long.MAX_VALUE");
System.out.println(" x = "+x);
while(x>0)
{
iy=maxFibo(x);
y=f[iy];
nrt++;
System.out.println(nrt+" : "+x+" f["+iy+"] = "+y);
x=x-y;
}
}
static int maxFibo(long nr)
{
int k;
for(k=1;k<=n;k++) if (f[k]>nr) break;
return k-1;
22 CAPITOLUL 1. EXERCIT II SIMPLE
}
}
1.1.24 Numarul permutarilor idempotente
import java.io.*; // numarul permutarilor idempotente p^2 = e in S_n
class PermIdempotente
{
static int n;
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("n = "); n = Integer.parseInt(br.readLine());
int[] np = new int[n+1];
np[0]=1;
np[1]=1;
for(int i=2;i<=n;i++)
{
np[i]=np[i-1]+(i-1)*np[i-2];
System.out.println(i+" : "+np[i]);
}
}
}
1.1.25 Fract ie continua: determinarea coecient ilor
class FractieContinua1
{
public static void main(String[] args)
{
int p=123,q=45;
int[] b=fracc(p,q);
for(int i=0;i<b.length;i++) System.out.print(b[i]+" ");
}
static int[] fracc(int p,int q)
{
int d, i, c, r, n=0;
d=p; i=q;
1.1. ALGORITMI ELEMENTARI 23
while(i!=0) // pentru calculul dimensiunii vectorului b
{
c=d/i; r=d%i; n++; d=i; i=r;
}
int[] b=new int[n];
int poz=0;
d=p; i=q;
while(i!=0) // pentru calculul coeficientilor vectorului b
{
c=d/i; r=d%i; b[poz]=c; poz++; d=i; i=r;
}
return b;
}
}
1.1.26 Fract ie continua: determinarea fract iei init iale
class FractieContinua2
{
public static void main(String[] args)
{
int p,q;
int[] b={2,1,2,1,3};
p=calcA(b); q=calcB(b);
System.out.println(p+"/"+q);
}//main
static int calcA(int[] b)
{
int n=b.length-1;
int[] A=new int[b.length];
A[0]=b[0];
A[1]=b[0]*b[1]+1;
for(int k=2;k<=n;k++)
A[k]=b[k]*A[k-1]+A[k-2];
return A[n];
}
static int calcB(int[]b)
{
int n=b.length-1;
int[] B=new int[b.length];
24 CAPITOLUL 1. EXERCIT II SIMPLE
B[0]=1;
B[1]=b[1];
for(int k=2;k<=n;k++)
B[k]=b[k]*B[k-1]+B[k-2];
return B[n];
}
}//class
1.1.27 Generare polinom cu radacini fract ionare date
class GenerarePolinom // RadaciniRationale p_i/q_i
{
public static void main(String[] args)
{
int[] p={1,1,2,3, 3, 1};
int[] q={2,3,3,2,-2,-1};
int[] a=genPol(p,q);
afisv(a);
}
static int[] genPol(int[] a, int[] b) // X-a_i/b_i==>b_i X - a_i
{
int n=a.length;
int[] p={-a[0],b[0]},// p=b[0] X -a[0]
q={13,13}; // q=initializat "aiurea" pentru dimensiune !
// afisv(p);
for(int k=1;k<n;k++)
{
q[0]=-a[k];
q[1]=b[k];
p=pxq(p,q);
// afisv(p);
}
return p;
}
static int[] pxq(int[] p,int[] q)
{
int gradp=p.length-1, gradq=q.length-1;
int gradpq=gradp+gradq;
int[] pq=new int[gradpq+1];
1.1. ALGORITMI ELEMENTARI 25
int i,j,k;
for(k=0;k<=gradpq;k++) pq[k]=0;
for(i=0;i<=gradp;i++)
for(j=0;j<=gradq;j++)
pq[i+j]+=p[i]*q[j];
return pq;
}
static void afisv(int[] a)
{
for(int i=a.length-1;i>=0;i--)
System.out.print(a[i]+" ");
System.out.println();
}
}// class
1.1.28 Radacini rat ionale
class RadaciniRationale
{
public static void main(String[] args)
{
int[] a={72, -36, -218, 125, 118, -99, 18};
int k=0, n=a.length-1, alfa, beta;
int moda0=Math.abs(a[0]);
int modan=Math.abs(a[n]);
for(alfa=1;alfa<=moda0;alfa++)
{
if(moda0%alfa!=0) continue;
for(beta=1;beta<=modan;beta++)
{
if(modan%beta!=0) continue;
if(cmmdc(alfa,beta)!=1) continue; // altfel, ... Caragiale!
if(f(a,alfa,beta)==0)
System.out.println("x["+(++k)+"] = "+alfa+"/"+beta+" ");
if(f(a,-alfa,beta)==0)
System.out.println("x["+(++k)+"] = -"+alfa+"/"+beta+" ");
}
}
}
static int f(int[]a,int alfa, int beta)
26 CAPITOLUL 1. EXERCIT II SIMPLE
{
int n=a.length-1,k,s=0;
for(k=0;k<=n;k++)
s+=a[k]*putere(alfa,k)*putere(beta,n-k);
return s;
}
static int putere(int a, int n)
{
int p=1;
for(int k=1;k<=n;k++) p*=a;
return p;
}
static int cmmdc(int a, int b)
{
int d,i,c,r;
if (a>b) {d=a; i=b;} else {d=b; i=a;}
while(i!= 0)
{
c=d/i; r=d%i; d=i; i=r;
}
return d;
}
}// class
1.1.29 Numarul divizorilor unui numar natural
class NumarDivizori
{
public static void main(String[] args)
{
int n=12;
System.out.println(n+" --> "+nrDivizori(n));
}
static int nrDivizori(int nr)
{
int d, nrd, p=1;
d=2;
nrd=0;
while(nr%d==0) { nrd++; nr=nr/d; }
1.1. ALGORITMI ELEMENTARI 27
p=p*(nrd+1);
d=3;
while(d*d<=nr)
{
nrd=0;
while(nr%d==0) { nrd++; nr=nr/d; }
p=p*(nrd+1);
d=d+2;
}
if(nr>1) p*=2;
return p;
}
}
1.1.30 Funct ia lui Euler
class EulerFunctia
{
public static void main(String [] args)
{
int n=12;
System.out.println(n+" --> "+fi(n));
}
static int fi(int n)
{
int card=0;
for(int k=1;k<=n;k++)
if(cmmdc(k,n)==1) card++;
return card;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) { d=a; i=b; } else { d=b; i=a; }
while(i!=0) { c=d/i;r=d%i; d=i; i=r; }
return d;
}
}
28 CAPITOLUL 1. EXERCIT II SIMPLE
1.1.31 Formula de calcul pentru funct ia lui Euler
class EulerCalcul
{
public static void main(String[] args)
{
int n=12;
System.out.println(n+" --> "+calculEuler(n));
}
static int calculEuler(int nr)
{
int d;
int nrd;
int p=1,nrr=nr;
d=2;
nrd=0;
while(nr%d==0)
{
nrd++;
nr=nr/d;
}
if(nrd>0) { p=p*(d-1); nrr=nrr/d; }
d=3;
while(d*d<=nr)
{
nrd=0;
while(nr%d==0) { nrd++; nr=nr/d; }
if(nrd>0) { p=p*(d-1); nrr=nrr/d; }
d=d+2;
}
if(nr>1) { p=p*(nr-1); nrr=nrr/nr; }
return p*nrr;
}
}
1.1.32 Ghiceste numarul
Se alege un num ar natural ntre 1 si n. Calculatorul ntreaba cum este fat a
de mijlocul extremelor curente (de la ecare pas). Numarul se ghiceste n maxim
1 + [log
2
(n)] pasi (ntrebari).
1.1. ALGORITMI ELEMENTARI 29
import java.io.*;
class GhicesteNr
{
static int nrIncercare=0;
public static void main(String[] args) throws IOException
{
int n=-1; // alege un numar intre 1 ... n
while (n<1)
{
scrieText("Alege (in minte) un numar intre 1 si ... : ");
n=getInt();
}
ghiceste(n);
}// main
static void ghiceste(int n) throws IOException
{
int p=1, q=n, raspuns, m;
boolean gasit=false;
while((p<=q)&&(gasit==false))
{
m=mijloc(p,q);
raspuns=propun(m);
switch(raspuns)
{
case 1: q=m-1; break; // mai mic
case 2: p=m+1; break; // mai mare
case 3: gasit=true; // URA !!!
}
}
if(gasit) scrieText("URAAAAA...!!!!");
else scrieText("Ai gresit la un raspuns...!!!!");
System.out.println();
}
static int mijloc(int p, int q) { return (p+q)/2; } // mijloc()
static int propun(int m) throws IOException
{
int raspuns=-1;
scrieText("Incercarea "+(++nrIncercare));
while((raspuns != 1)&&(raspuns != 2)&&(raspuns != 3))
30 CAPITOLUL 1. EXERCIT II SIMPLE
{
scrieText("Cum este fata de "+m+" ?");
scrieText("1 = mai mic; 2 = mai mare; 3 = EGAL raspuns: ");
raspuns = getInt();
}
return raspuns;
} // propun()
static void scrieText(String s)
{
System.out.print("\n"+s);
System.out.flush();
}
public static String getString() throws IOException
{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine(); return s;
} // getString()
public static int getInt() throws IOException
{
String s = getString();
return Integer.parseInt(s);
}
}
1.1.33 Calculul funct iei arcsin
Dezvoltarea n serie a funct iei este urmatoarea:
arcsin(x) = x +
1
2
x
3
3
+
1
2
3
4
x
5
5
+... +
1
2
3
4
...
2n 3
2n 2
x
2n1
2n 1
+...
= t
1
+t
2
+t
3
+... +t
n
+...
Se poate observa ca:
t
1
= x si t
k+1
=
x x (2k 1) (2k 1)
2k(2k + 1)
t
k
pentru k 1
Vom calcula o suma nita (adaugam termeni pana cand modulul diferent ei
a doi termeni consecutivi este inferior unei valori date si far a a depasi num arul
nMax de termeni din serie).
1.1. ALGORITMI ELEMENTARI 31
class ArcSinus
{
static double dif;
static int k;
public static void main(String[] args)
{
double x=Math.sin(Math.toRadians(-60)),eps=1.0e-15;
int nMax=100000;
System.out.println("arcsin("+x+") = "+
Math.toDegrees(arcSinus(x,eps,nMax))+"\t"+dif+"\t"+k);
}
static double arcSinus(double x, double eps, int nMax)
{
double tk=x,s=tk,tk1=0;
dif=0;
k=1;
do
{
tk1=tk*x*x*(2*k-1)*(2*k-1)/(4*k*k+2*k);
s+=tk1;
dif=Math.abs(tk1-tk);
tk=tk1;
k++;
} while((dif>eps)&&(k<nMax));
return s;
}
}
1.1.34 Algoritmul lui Euclid extins
class EuclidExtins // cmmdc(a,b) = alfa*a + beta*b unde a>b>0
{ // inlocuiesc resturile de la sfarsit spre inceput !!!
static final int NMAX=20;
static int[] r = new int[NMAX],
c = new int[NMAX],
alfa = new int[NMAX],
beta = new int[NMAX];
public static void main(String[] args)
{
32 CAPITOLUL 1. EXERCIT II SIMPLE
int a=221,b=29;
//int a=614, b=513;
if(a>b) {r[0]=a; r[1]=b;} else {r[0]=b; r[1]=a;}
int k=0;
do
{
k++;
c[k]=r[k-1]/r[k];
r[k+1]=r[k-1]%r[k];
System.out.println(r[k-1]+"="+c[k]+"*"+r[k]+"+"+r[k+1]);
} while (r[k+1]!=0);
int cmmdc=r[k];
System.out.print("cmmdc("+a+","+b+") = "+cmmdc);
int n=k-1;
alfa[n]=1;
beta[n]=-c[n];
for(int i=n-1;i>=1;i--)
{
alfa[i]=beta[i+1];
beta[i]=alfa[i+1]-c[i]*beta[i+1];
}
System.out.println(" = ("+alfa[1]+")*"+r[0]+" + ("+beta[1]+")*"+r[1]);
}
}
/* OBS:
initializari: r[0]=max(a,b); r[1]=min(a,b);
algoritm: r[0] = r[1]c[1]+r[2]
r[1] = r[2]c[2]+r[3]
r[2] = r[3]c[3]+r[4]
...
r[n-2] = r[n-1]c[n-1]+r[n] cmmdc(a,b)=r[n]
r[n-1] = r[n]c[n]+0 (gata!!!) ===============
*/
1.2 Calculul unor sume si produse
1.2.1 Calculul funct iei arcsin
1.2. CALCULUL UNOR SUME SI PRODUSE 33
1.2.2 Calcul f(n) =
n
k=0
1
2
k
C
n
n+k
class SP01
{
public static void main(String[]args)
{
int n=10;
int k, s, p;
s=0;
for(k=0;k<=n;k++)
{
p=comb(n+k,n)*putere(2,n-k);
s=s+p;
}
s=s/putere(2,n);
System.out.println("f("+n+") = "+s);
}
static int putere(int a, int n)
{
int k,p;
p=1;
for(k=1;k<=n;k++) p=p*a;
return p;
}
static int comb(int n, int k)
{
if(k>n/2) k=n-k;
int p;
int i,j, d;
int[]x=new int[k+1];
int[]y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
34 CAPITOLUL 1. EXERCIT II SIMPLE
}
p=1;
for(i=1;i<=k;i++) p=p*x[i];
return p;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if (a>b) {d=a;i=b;} else {d=b;i=a;}
while (i!=0) { c=d/i; r=d%i; d=i; i=r; }
return d;
}
}
1.2.3 Calcul f(n) =
n1
k=0
C
k
n1
n
n1k
(k + 1)!
class SP02
{
public static void main(String[]args)
{
int n=4;
int s, p, k;
s=0;
for(k=0;k<=n-1;k++)
{
p=comb(n-1,k)*putere(n,n-1-k);
p=p*factorial(k+1);
s=s+p;
}
System.out.println("f("+n+") = "+s);
}
static int comb(int n,int k)
{
if(k>n/2) k=n-k;
int i,j,d;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(i=1;i<=k;i++) y[i]=i;
for(j=2;j<=k;j++)
1.2. CALCULUL UNOR SUME SI PRODUSE 35
for(i=1;i<=k;i++)
{
d=cmmdc(x[i],y[j]);
x[i]=x[i]/d;
y[j]=y[j]/d;
if(y[j]==1) break;
}
int p=1;
for(i=1;i<=k;i++) p=p*x[i];
return p;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if (a>b) {d=a;i=b;}else {d=b;i=a;}
while(i!=0){c=d/i;r=d%i;d=i;i=r;}
return d;
}
static int putere(int a,int n)
{
int k;
int p;
p=1;
for(k=1;k<=n;k++) p=p*a;
return p;
}
static int factorial(int n)
{
int k;
int p;
p=1;
for(k=1;k<=n;k++) p=p*k;
return p;
}
}// class
1.2.4 Calcul f(n) = n
n1
+
n1
k=1
C
k
n
k
k1
(n k)
nk
class SP03
36 CAPITOLUL 1. EXERCIT II SIMPLE
{
public static void main(String[]args)
{
int n=5;
int s, p, k;
s=0;
for(k=1;k<=n-1;k++)
{
p=comb(n,k)*putere(k,k-1);
p=p*putere(n-k,n-k);
s=s+p;
}
s=s+putere(n,n-1);
System.out.println("f("+n+") = "+s);
}
static int comb(int n,int k)
{
if(k>n/2) k=n-k;
int i,j,d;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(i=1;i<=k;i++) y[i]=i;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(x[i],y[j]);
x[i]=x[i]/d;
y[j]=y[j]/d;
if(y[j]==1) break;
}
int p=1;
for(i=1;i<=k;i++) p=p*x[i];
return p;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;}else {d=b;i=a;}
while(i!=0){c=d/i;r=d%i;d=i;i=r;}
return d;
}
1.2. CALCULUL UNOR SUME SI PRODUSE 37
static int putere(int a,int n)
{
int k;
int p;
p=1;
for(k=1;k<=n;k++) p=p*a;
return p;
}
}// class
1.2.5 Calcul f(n) = n!
_
1
1
1!
+
1
2!
... +
(1)
n
n!
_
Aceast a formula reprezint a num arul permutarilor far a puncte xe.
class SP04
{
public static void main(String [] args)
{
long n=15, k, s=0L, xv, xn; // n=22 maxim pe long !
if((n&1)==1) xv=-1L; else xv=1L;
s=xv;
for(k=n;k>=3;k--)
{
xn=-k*xv;
s+=xn;
xv=xn;
}
System.out.println("f("+n+") = "+s);
System.out.println("MaxLong= "+Long.MAX_VALUE);
}
}
1.2.6 Calcul s(n, m) =
m1
k=0
C
k
m
(1)
k
(mk)
n
s(n, m) reprezint a num arul funct iilor surjective f : {1, 2, ..., n} {1, 2, ..., m}.
class SP05
{
public static void main (String[]args)
{
int n;
38 CAPITOLUL 1. EXERCIT II SIMPLE
int m=5;
int k, s;
for(n=1;n<=10;n++)
{
s=0;
for(k=0;k<=m-1;k++)
s=s+comb(m,k)*putere(-1,k)*putere(m-k,n);
System.out.println("s("+n+","+m+") = "+s);
}
}
static int putere(int a, int n)
{
int rez;
int k;
rez=1;
for(k=1;k<=n;k++) rez=rez*a;
return rez;
}
static int comb(int n, int k)
{
int rez;
int i,j,d;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
rez=1;
for(i=1;i<=k;i++) rez=rez*x[i];
return rez;
}
static int cmmdc (int a,int b)
{
int d,i,c,r;
1.2. CALCULUL UNOR SUME SI PRODUSE 39
if(a>b) {d=a;i=b;} else{d=b;i=a;}
while(i!=0){ c=d/i; r=d%i; d=i; i=r; }
return d;
}
}
1.2.7 Calcul f(m, n,
1
, ...,
n
) = (C
1
m
)
1
...
_
C
n
m+n1
_
n
class SP06
{
public static void main(String[] args)
{
int m=2;
int n=3;
int k;
int[] lam=new int[n+1];
int rez;
lam[1]=1;
lam[2]=3;
lam[3]=2;
rez=1;
for(k=0;k<=n-1;k++)
rez=rez*putere(comb(m+k,k+1),lam[k+1]);
System.out.println("rez = "+rez);
}
static int putere(int a,int n)
{
int i;
int rez=1;
for(i=1;i<=n;i++) rez=rez*a;
return rez;
}
static int comb(int n,int k)
{
if(k>n/2) k=n-k;
int i,j,d;
int rez;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
40 CAPITOLUL 1. EXERCIT II SIMPLE
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
rez=1;
for(i=1;i<=k;i++) rez=rez*x[i];
return rez;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else {d=b;i=a;}
while(i!=0) { c=d/i; r=d%i; d=i; i=r; }
return d;
}
}
1.2.8 Calcul f(...) =
m
k=1
(1)
mk
_
C
k
m
_
(C
1
k
)
1
...
_
C
n
k+n1
_
n
class SP07
{
public static void main(String[] args)
{
int m=2;
int n=3;
int k,i,s;
int[] lam=new int[n+1];
int rez;
lam[1]=1;
lam[2]=3;
lam[3]=2;
s=0;
for(k=1;k<=m;k++)
{
rez=1;
1.2. CALCULUL UNOR SUME SI PRODUSE 41
for(i=1;i<=n;i++)
rez=rez*putere(comb(k+i-1,i),lam[i]);
s=s+putere(-1,m-k)*comb(m,k)*rez;
}
System.out.println("s = "+s);
}
static int putere(int a,int n)
{
int i,rez=1;
for(i=1;i<=n;i++) rez=rez*a;
return rez;
}
static int comb(int n,int k)
{
int i,j,d;
int rez;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
rez=1;
for(i=1;i<=k;i++) rez=rez*x[i];
return rez;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else {d=b;i=a;}
while(i!=0) { c=d/i; r=d%i; d=i; i=r; }
return d;
}
}
42 CAPITOLUL 1. EXERCIT II SIMPLE
1.2.9 Calcul f(n) =
1
2
n
n
k=0
(1)
k
C
k
n
2
k
(2n k)!
class SP08
{
public static void main(String[] args)
{
int n=4;
int s,k;
s=0;
for(k=0;k<=n;k++)
s=s+putere(-1,k)*comb(n,k)*putere(2,k)*fact(2*n-k);
s=s/putere(2,n);
System.out.println("s="+s);
}
static int putere(int a,int n)
{
int i,rez=1;
for(i=1;i<=n;i++) rez=rez*a;
return rez;
}
static int fact(int n)
{
int i,rez=1;
for(i=1;i<=n;i++) rez=rez*i;
return rez;
}
static int comb(int n,int k)
{
if(k>n/2) k=n-k;
int i,j,d;
int rez;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
1.2. CALCULUL UNOR SUME SI PRODUSE 43
x[i]=x[i]/d;
if(y[j]==1) break;
}
rez=1;
for(i=1;i<=k;i++) rez=rez*x[i];
return rez;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else {d=b;i=a;}
while(i!=0) { c=d/i; r=d%i; d=i; i=r; }
return d;
}
}
1.2.10 Numerele Stirling de spet a a II-a
Fie S(n, m) num arul modalit at ilor de partit ionare a unei mult imi cu n ele-
mente n m submult imi nevide (de exemplu, plasare numerelor {1, 2, ..., n} n m
cutii identice si nenumerotate astfel ncat nici o cutie s a nu e goala!). Acest num ar
ndeplineste urmatoarea relat ie de recurent a:
S(n + 1, m) = S(n, m) +mS(n, m) unde S(n, n) = S(n, 1) = 1.
Scriet i un program care s a calculeze, de exemplu, S(11, 2).
class SP09
{
public static void main(String[] args)
{
int n=11,m=2; // n >= m
int i, j, jmin;
long t1,t2;
int[][] a=new int[n+1][m+1];
t1=System.currentTimeMillis();
for(i=1;i<=n;i++) a[i][1]=1;
for(i=1;i<=m;i++) a[i][i]=1;
for(i=3;i<=n;i++)
{
jmin=min(m,i-1);
for(j=2;j<=jmin;j++)
a[i][j]=a[i-1][j-1]+a[i-1][j]*j;
44 CAPITOLUL 1. EXERCIT II SIMPLE
}
System.out.println(a[n][m]);
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}
static int min(int a, int b)
{
if(a<b) return a; else return b;
}
}
1.2.11 Numerele lui Bell
Fie B(n) num arul partit iilor unei mult imi nite cu n elemente n submult imi
nevide. Acest num ar ndeplineste urmatoarea relat ie de recurent a:
B(n + 1) =
n
k=0
C
k
n
B(k) unde B(0) = 1.
Scriet i un program care s a calculeze, de exemplu, B(15).
class SP10
{
public static void main(String[] args)
{
int n=15; // n=15(25) ultimul care incape pe int(long)
int k,i;
int[] b=new int[n+1];
int prod=1;
b[0]=1;
for(i=1;i<=n;i++)
{
b[i]=0;;
for(k=0;k<=i-1;k++)
{
prod=comb(i-1,k)*b[k];
b[i]=b[i]+prod;
}
System.out.println(i+" : "+b[i]);
}
System.out.println(" "+Integer.MAX_VALUE);
}
1.2. CALCULUL UNOR SUME SI PRODUSE 45
static int comb(int n,int k)
{
int i,j,d;
int rez;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
rez=1;
for(i=1;i<=k;i++) rez=rez*x[i];
return rez;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else {d=b;i=a;}
while(i!=0) { c=d/i; r=d%i; d=i; i=r; }
return d;
}
}
1.2.12 Partit iile unui numar natural
Fie P(n, m) num arul modalit at ilor de partit ionare a num arului natural n ca
suma de m numere naturale far a a se t ine cont de ordinea acestora n suma (n
scrierea n = a
1
+a
2
+... +a
m
presupunem a
1
a
2
... a
m
1). Acest num ar
ndeplineste urmatoarea relat ie de recurent a:
P(n +k, k) = P(n, 1) +P(n, 2) +... +P(n, k) unde P(n, n) = P(n, 1) = 1.
Scriet i un program care s a calculeze, de exemplu, P(12, 3).
class SP11
{
46 CAPITOLUL 1. EXERCIT II SIMPLE
public static void main(String[] args)
{
int n=12,m=3;
int[][] p=new int[n+1][n+1];
int nsol;
int i,j,k;
p[1][1]=1;
for(i=2;i<=n;i++)
{
p[i][i]=p[i][1]=1;
for(j=2;j<i;j++)
{
p[i][j]=0;
for(k=1;k<=j;k++) p[i][j]=p[i][j]+p[i-j][k];
}
}
afism(p);
nsol=0;
for(j=1;j<=n;j++) nsol=nsol+p[n][j];
System.out.println("nsol = "+nsol);
System.out.println("P("+n+","+m+") = "+p[n][m]);
}
static void afism(int[][] a)
{
int i,j;
int n=a.length;
int m;
for(i=1;i<n;i++)
{
m=a[i].length;
System.out.print(i+": ");
for(j=1;j<=i;j++) System.out.print(a[i][j]+" ");
System.out.println();
}
System.out.println();
}
}
1.2.13 Recurent a Catalan: C
n
=
n
k=1
C
k1
C
nk
unde C
0
= 1
1.2. CALCULUL UNOR SUME SI PRODUSE 47
class SP12
{
public static void main(String[] args)
{
int n=17,i,k;
int p;
int s;
int[] c=new int[n+1];
c[0]=1;
for(i=1;i<=n;i++)
{
s=0;
for(k=1; k<=i; k++)
{
p=c[k-1]*c[i-k];
s=s+p;
}
c[i]=s;
System.out.println(i+" : "+c[i]);
}
}
}
1.2.14 Recurent a: E
n
= E
2
E
n1
+ E
3
E
n2
+ ... + E
n1
E
2
unde
E
1
= E
2
= 1
class SP13
{
public static void main(String[] args)
{
int n=19,i,k;
int p;
int s;
int[] e=new int[n+1];
e[1]=e[2]=1;
for(i=3;i<=n;i++)
{
s=0;
for(k=2; k<=i-1; k++)
{
p=e[k]*e[i-k+1];
48 CAPITOLUL 1. EXERCIT II SIMPLE
s=s+p;
}
e[i]=s;
System.out.println(i+" : "+e[i]);
}
}
}
1.2.15 Numerele Stirling de spet a a II-a
Fie S(n, m) num arul modalit at ilor de partit ionare a unei mult imi cu n ele-
mente n m submult imi nevide (de exemplu, plasare numerelor {1, 2, ..., n} n m
cutii identice si nenumerotate astfel ncat nici o cutie s a nu e goala!). Acest num ar
se poate calcula cu formula:
S(n, m) =
1
m!
m1
k=0
(1)
k
C
k
m
(mk)
n
.
Scriet i un program care s a calculeze, de exemplu, S(11, 2).
class SP14
{
public static void main(String[]args)
{
int n=11,m=2;
int s, p, k;
s=0;
for(k=0;k<=m-1;k++)
{
p=putere(-1,k)*comb(m,k);
p=p*putere(m-k,n);
s=s+p;
}
s=s/factorial(m);
System.out.println("S("+n+","+m+") = "+s);
}
static int comb(int n,int k)
{
if(k>n/2) k=n-k;
int i,j,d;
int[] x=new int[k+1];
int[] y=new int[k+1];
1.2. CALCULUL UNOR SUME SI PRODUSE 49
for(i=1;i<=k;i++) x[i]=n-k+i;
for(i=1;i<=k;i++) y[i]=i;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(x[i],y[j]);
x[i]=x[i]/d;
y[j]=y[j]/d;
if(y[j]==1) break;
}
int p=1;
for(i=1;i<=k;i++) p=p*x[i];
return p;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if (a>b) {d=a;i=b;}else {d=b;i=a;}
while(i!=0){c=d/i;r=d%i;d=i;i=r;}
return d;
}
static int putere(int a,int n)
{
int k;
int p;
p=1;
for(k=1;k<=n;k++) p=p*a;
return p;
}
static int factorial(int n)
{
int k;
int p;
p=1;
for(k=1;k<=n;k++) p=p*k;
return p;
}
}// class
50 CAPITOLUL 1. EXERCIT II SIMPLE
1.2.16 Calcul f(n) =
n
k=0
C
k
n
F
k
class SP15
{
static int n=15;
static int[] f=new int[n+1];
public static void main(String[] args)
{
int k,i;
f[0]=0;
f[1]=1;
for(k=2;k<=n;k++) f[k]=f[k-1]+f[k-2];
int[] x=new int[n+1];
int prod=1;
for(i=1;i<=n;i++)
{
x[i]=0;;
for(k=0;k<=i;k++)
{
prod=comb(i,k)*f[k];
x[i]=x[i]+prod;
}
System.out.println(i+" : "+x[i]+" "+f[i]);
}
}
static int comb(int n,int k)
{
if(k>n/2) k=n-k;
int i,j,d;
int rez;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
1.2. CALCULUL UNOR SUME SI PRODUSE 51
if(y[j]==1) break;
}
rez=1;
for(i=1;i<=k;i++) rez=rez*x[i];
return rez;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else {d=b;i=a;}
while(i!=0) { c=d/i; r=d%i; d=i; i=r;}
return d;
}
}
1.2.17 Calcul f(n) =
n
k=0
C
k
n
2
k
F
k
class SP16
{
static int n=15;
static int[] f=new int[n+1];
public static void main(String[] args)
{
int k,i;
f[0]=0;
f[1]=1;
for(k=2;k<=n;k++) f[k]=f[k-1]+f[k-2];
int[] x=new int[n+1];
int prod=1;
for(i=1;i<=n;i++)
{
x[i]=0;;
for(k=0;k<=i;k++)
{
prod=comb(i,k)*putere(2,k)*f[k];
x[i]=x[i]+prod;
}
System.out.println(i+" : "+x[i]+" "+f[i]);
}
52 CAPITOLUL 1. EXERCIT II SIMPLE
}
static int comb(int n,int k)
{
if(k>n/2) k=n-k;
int i,j,d;
int rez;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
}
rez=1;
for(i=1;i<=k;i++) rez=rez*x[i];
return rez;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else {d=b;i=a;}
while(i!=0) {c=d/i; r=d%i; d=i; i=r; }
return d;
}
static int putere(int a,int n)
{
int k;
int p;
p=1;
for(k=1;k<=n;k++) p=p*a;
return p;
}
}
Capitolul 2
Simularea operat iilor cu
numere mari
2.1 Operat ii cu numere mari
2.1.1 Vectorul cifrelor unui numar
class NrV
{
public static void main(String[] args)
{
int nr=232425;
int[] x=nrv(nr);
afisv(x);
}
static void afisv(int[] x)
{
int nx=x.length;
int i;
for(i=nx-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] nrv(int nr)
{
53
54 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
int nc;
int nrrez=nr;
nc=0;
while(nr!=0) {nc++; nr=nr/10;}
int[] x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0)
{
x[nc]=nr%10;
nc++;
nr=nr/10;
}
return x;
}
}
2.1.2 Adunarea numerelor mari
class SumaNrMari
{
public static void main(String[] args)
{
int[] x=nrv(123); afisv(x);
int[] y=nrv(456); afisv(y);
int[] z=suma(x,y);
afisv(z);
}
static void afisv(int[] x)
{
int nx=x.length;
int i;
for(i=nx-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] nrv(int nr)
{
int nc;
int nrrez=nr;
nc=0;
2.1. OPERAT II CU NUMERE MARI 55
while(nr!=0) { nc++; nr=nr/10; }
int[] x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0)
{
x[nc]=nr%10;
nc++;
nr=nr/10;
}
return x;
}
static int[] suma(int[] x,int[] y)
{
int k,s,t;
int nx=x.length;
int ny=y.length;
int nz;
if(nx>ny) nz=nx+1; else nz=ny+1;
int[] z=new int[nz];
t=0;
for(k=0;k<nz;k++)
{
s=t;
if(k<nx) s=s+x[k];
if(k<ny) s=s+y[k];
z[k]=s%10;
t=s/10;
}
if(z[nz-1]!=0) return z;
else
{
int[] zz=new int[nz-1];
for(k=0;k<nz-1;k++) zz[k]=z[k];
return zz;
}
}
}
2.1.3
Inmult irea numerelor mari
56 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
class ProdusNrMari
{
public static void main(String[] args)
{
int[] x=nrv(12); afisv(x);
int[] y=nrv(9); afisv(y);
int[] z=produs(x,y);
afisv(z);
}
static void afisv(int[] x)
{
int nx=x.length;
int i;
for(i=nx-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] nrv(int nr)
{
int nc;
int nrrez=nr;
nc=0;
while(nr!=0) {nc++; nr=nr/10;}
int[] x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0)
{
x[nc]=nr%10;
nc++;
nr=nr/10;
}
return x;
}
static int[] produs(int[] x,int[] y)
{
int i,j,t,s;
int nx=x.length;
int ny=y.length;
int nz=nx+ny;
int[][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
2.1. OPERAT II CU NUMERE MARI 57
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
s=t+y[j]*x[i];
a[j][i+j]=s%10;
t=s/10;
}
a[j][i+j]=t;
}
t=0;
for(j=0;j<nz;j++)
{
s=0;
for(i=0;i<ny;i++) s=s+a[i][j];
s=s+t;
z[j]=s%10;
t=s/10;
}
if(z[nz-1]!=0) return z;
else
{
int[] zz=new int[nz-1];
for(j=0;j<zz.length;j++) zz[j]=z[j];
return zz;
}
}
}
2.1.4
Impart irea numerelor mari la 2
class ImpartLa2NrMari
{
public static void main(String[] args)
{
int[] x=nrv(1234); afisv(x);
int[] y=impartLa2(x);
afisv(y);
}
static void afisv(int[] x)
58 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
{
int nx=x.length;
int i;
for(i=nx-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] nrv(int nr)
{
int nc;
int nrrez=nr;
nc=0;
while(nr!=0) {nc++; nr=nr/10;}
int[] x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0)
{
x[nc]=nr%10;
nc++;
nr=nr/10;
}
return x;
}
static int[] impartLa2(int[] a)
{
int na,nb,k,t=0;
na=a.length-1;
if(a[na]==1) nb=na-1; else nb=na;
int[] b=new int[nb+1];
if(na==nb)
for(k=na;k>=0;k--)
{
a[k]+=10*t;
b[k]=a[k]/2;
t=a[k]%2;
}
else
{
t=a[na];
for(k=na-1;k>=0;k--)
{
a[k]+=10*t;
2.1. OPERAT II CU NUMERE MARI 59
b[k]=a[k]/2;
t=a[k]%2;
}
}
return b;
}
}
2.1.5 Funct ia putere cu numere mari
import java.io.*;
class PutereNRMari
{
public static void main (String[]args) throws IOException
{
int a,n;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("a = "); a=Integer.parseInt(br.readLine());
System.out.print("n = "); n=Integer.parseInt(br.readLine());
System.out.print("putere("+a+","+n+") = "); afisv(putere(a,n));
}
static int[] nrv(int nr)
{
int nc;
int nrrez=nr;
nc=0;
while(nr!=0) {nc++; nr=nr/10;}
int[] x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0)
{
x[nc]=nr%10;
nc++;
nr=nr/10;
}
return x;
}
static int[] putere(int a,int n)
60 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
{
int k;
int[] p;
p=nrv(1);
for(k=1;k<=n;k++) p=produs(p,nrv(a));
return p;
}
static void afisv(int[] x)
{
int nx=x.length;
int i;
for(i=nx-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] produs(int[] x,int[] y)
{
int i,j,t,s;
int nx=x.length;
int ny=y.length;
int nz=nx+ny;
int [][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
s=t+y[j]*x[i];
a[j][i+j]=s%10;
t=s/10;
}
a[j][i+j]=t;
}
t=0;
for(j=0;j<nz;j++)
{
s=0;
for(i=0;i<ny;i++)
s=s+a[i][j];
s=s+t;
z[j]=s%10;
t=s/10;
2.1. OPERAT II CU NUMERE MARI 61
}
if(z[nz-1]!=0)return z;
else
{
int[] zz=new int[nz-1];
for(j=0;j<zz.length;j++)
zz[j]=z[j];
return zz;
}
}
}
2.1.6 Funct ia factorial cu numere mari
import java.io.*;
class PutereNRMari
{
public static void main (String[]args) throws IOException
{
int a,n;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("n = "); n=Integer.parseInt(br.readLine());
System.out.print(n+"! = "); afisv(factorial(n));
}
static int[] nrv(int nr)
{
int nc;
int nrrez=nr;
nc=0;
while(nr!=0) {nc++; nr=nr/10;}
int[] x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0)
{
x[nc]=nr%10;
nc++;
nr=nr/10;
}
return x;
62 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
}
static int[] int[] factorial(int n)
{
int k;
int[] p;
p=nrv(1);
for(k=1;k<=n;k++) p=produs(p,nrv(k));
return p;
}
static void afisv(int[] x)
{
int nx=x.length;
int i;
for(i=nx-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] produs(int[] x,int[] y)
{
int i,j,t,s;
int nx=x.length;
int ny=y.length;
int nz=nx+ny;
int [][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
s=t+y[j]*x[i];
a[j][i+j]=s%10;
t=s/10;
}
a[j][i+j]=t;
}
t=0;
for(j=0;j<nz;j++)
{
s=0;
for(i=0;i<ny;i++)
s=s+a[i][j];
2.1. OPERAT II CU NUMERE MARI 63
s=s+t;
z[j]=s%10;
t=s/10;
}
if(z[nz-1]!=0)return z;
else
{
int[] zz=new int[nz-1];
for(j=0;j<zz.length;j++)
zz[j]=z[j];
return zz;
}
}
}
2.1.7 Calculul combinarilor cu numere mari
import java.io.*;
class CombinariNrMari
{
public static void main (String[]args) throws IOException
{
int n, k;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("n = "); n=Integer.parseInt(br.readLine());
System.out.print("k = "); k=Integer.parseInt(br.readLine());
System.out.print("combinari("+n+","+k+") = "); afisv(comb(n,k));
}
static int[] comb(int n,int k)
{
int i,j,d;
if(k>n/2) k=n-k; // o mica optimizare !
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(x[i],y[j]);
64 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
x[i]=x[i]/d;
y[j]=y[j]/d;
if(y[j]==1) break;
}
int[] p=nrv(1);
for(i=1;i<=k;i++) p=produs(p,nrv(x[i]));
return p;
}
static int cmmdc(int a, int b)
{
int d,i,c,r;
if (a>b) {d=a; i=b;} else {d=b; i=a;}
while (i != 0)
{
c=d/i; // nu se foloseste !
r=d%i;
d=i;
i=r;
}
return d;
}
static int[] nrv(int nr)
{
int nc;
int nrrez=nr;
nc=0;
while(nr!=0) {nc++; nr=nr/10;}
int[] x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0)
{
x[nc]=nr%10;
nc++;
nr=nr/10;
}
return x;
}
static void afisv(int[] x)
{
int nx=x.length;
2.1. OPERAT II CU NUMERE MARI 65
int i;
for(i=nx-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] produs(int[] x,int[] y)
{
int i,j,t,s;
int nx=x.length;
int ny=y.length;
int nz=nx+ny;
int [][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
s=t+y[j]*x[i];
a[j][i+j]=s%10;
t=s/10;
}
a[j][i+j]=t;
}
t=0;
for(j=0;j<nz;j++)
{
s=0;
for(i=0;i<ny;i++)
s=s+a[i][j];
s=s+t;
z[j]=s%10;
t=s/10;
}
if(z[nz-1]!=0)return z;
else
{
int[] zz=new int[nz-1];
for(j=0;j<zz.length;j++)
zz[j]=z[j];
return zz;
}
}
}
66 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
2.2 Sume si produse cu numere mari
2.2.1 Numarul lui Catalan C
n
=
1
n+1
C
n
2n
cu numere mari
import java.io.*;
class CatalanNrMari
{
public static void main (String[]args) throws IOException
{
int n,k;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
System.out.print("n = "); n=Integer.parseInt(br.readLine());
System.out.print("catalan("+n+") = "); afisv(catalan(n));
}
static int[] catalan(int n)
{
int i,j,d;
int[] x=new int[n+1];
int[] y=new int[n+1];
for(i=2;i<=n;i++) x[i]=n+i;
for(i=2;i<=n;i++) y[i]=i;
for(j=2;j<=n;j++)
for(i=2;i<=n;i++)
{
d=cmmdc(x[i],y[j]);
x[i]=x[i]/d;
y[j]=y[j]/d;
if(y[j]==1) break;
}
int[] p=nrv(1);
for(i=2;i<=n;i++) p=produs(p,nrv(x[i]));
return p;
}
static int cmmdc(int a, int b)
{
int d,i,c,r;
if(a>b) {d=a; i=b;} else {d=b; i=a;}
2.2. SUME SI PRODUSE CU NUMERE MARI 67
while (i != 0)
{
c=d/i; // nu se foloseste !
r=d%i;
d=i;
i=r;
}
return d;
}
static int[] nrv(int nr)
{
int nc;
int nrrez=nr;
nc=0;
while(nr!=0) {nc++; nr=nr/10;}
int[] x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0)
{
x[nc]=nr%10;
nc++;
nr=nr/10;
}
return x;
}
static void afisv(int[] x)
{
int nx=x.length;
int i;
for(i=nx-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] produs(int[] x,int[] y)
{
int i,j,t,s;
int nx=x.length;
int ny=y.length;
int nz=nx+ny;
int[][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
68 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
s=t+y[j]*x[i];
a[j][i+j]=s%10;
t=s/10;
}
a[j][i+j]=t;
}
t=0;
for(j=0;j<nz;j++)
{
s=0;
for(i=0;i<ny;i++)
s=s+a[i][j];
s=s+t;
z[j]=s%10;
t=s/10;
}
if(z[nz-1]!=0)return z;
else
{
int[] zz=new int[nz-1];
for(j=0;j<zz.length;j++) zz[j]=z[j];
return zz;
}
}
}
2.2.2 Calcul f(n) =
n
k=0
1
2
k
C
n
n+k
cu numere mari
class SP01NrMari
{
public static void main (String[]args)
{
int n;
int k;
int[] s;
int[] p;
for(n=1;n<=25;n++)
2.2. SUME SI PRODUSE CU NUMERE MARI 69
{
s=nrv(0);
for(k=0;k<=n;k++)
{
p=inm(comb(n+k,n),putere(2,n-k));
s=suma(s,p);
}
for(k=1;k<=n;k++) s=impartLa2(s);
System.out.print(n+" : ");
afisv(s);
}
}//main()
static int[] impartLa2(int[] a)
{
int na,nb,k,t=0;
na=a.length-1;
if(a[na]==1) nb=na-1; else nb=na;
int[] b=new int[nb+1];
if(na==nb)
for(k=na;k>=0;k--)
{
a[k]+=10*t;
b[k]=a[k]/2;
t=a[k]%2;
}
else
{
t=a[na];
for(k=na-1;k>=0;k--)
{
a[k]+=10*t;
b[k]=a[k]/2;
t=a[k]%2;
}
}
return b;
}
static int[] suma(int[] x, int[] y)
{
int i,j,t;
int ncx=x.length;
int ncy=y.length;
70 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
int ncz;
if(ncx>ncy) ncz=ncx+1; else ncz=ncy+1;
int[] xx=new int[ncz];
int[] yy=new int[ncz];
int[] z=new int[ncz];
for(i=0;i<ncx;i++) xx[i]=x[i];
for(j=0;j<ncy;j++) yy[j]=y[j];
t=0;
for(i=0;i<ncz;i++)
{
z[i]=xx[i]+yy[i]+t;
t=z[i]/10;
z[i]=z[i]%10;
}
if(z[ncz-1]!= 0) return z;
else
{
int[]zz=new int[ncz-1];
for(i=0;i<=ncz-2;i++) zz[i]=z[i];
return zz;
}
}
static int[] inm(int[]x,int[]y)
{
int t;
int n=x.length;
int m=y.length;
int i,j;
int[][]a=new int[m][n+m];
int[]z=new int[m+n];
for(j=0;j<m;j++)
{
t=0;
for(i=0;i<n;i++)
{
a[j][i+j]=y[j]*x[i]+t;
t=a[j][i+j]/10;
a[j][i+j]=a[j][i+j]%10;
}
a[j][i+j]=t;
}
t=0;
for(j=0;j<m+n;j++)
2.2. SUME SI PRODUSE CU NUMERE MARI 71
{
z[j]=0;
for(i=0;i<m;i++) z[j]=z[j]+a[i][j];
z[j]=z[j]+t;
t=z[j]/10;
z[j]=z[j]%10;
}
if(z[m+n-1]!= 0) return z;
else
{
int[] zz=new int[m+n-1];
for(i=0;i<=m+n-2;i++) zz[i]=z[i];
return zz;
}
}
static void afisv(int[]x)
{
int i;
for(i=x.length-1;i>=0;i--) System.out.print(x[i]);
System.out.print(" ---> "+x.length+" cifre");
System.out.println();
}
static int[] nrv(int nr)
{
int nrrez=nr;
int nc=0;
while(nr!=0) { nc++; nr=nr/10; }
int[]x =new int [nc];
nr=nrrez;
nc=0;
while(nr!=0) { x[nc]=nr%10; nc++; nr=nr/10; }
return x;
}
static int[] putere(int a, int n)
{
int[] rez;
int k;
rez=nrv(1);
for(k=1;k<=n;k++) rez=inm(rez,nrv(a));
return rez;
}
72 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
static int[] comb (int n, int k)
{
int[] rez;
int i,j;
int d;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
}
rez=nrv(1);
for(i=1;i<=k;i++) rez=inm(rez,nrv(x[i]));
return rez;
}
static int cmmdc (int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else {d=b;i=a;}
while (i!=0){ c=d/i; r=d%i; d=i; i=r;}
return d;
}
}
2.2.3 Calcul f(n) =
n1
k=0
C
k
n1
n
n1k
(k + 1)! cu numere mari
class SP02NrMari
{
public static void main(String[]args)
{
int n=12;
int[] s;
int[] p;
2.2. SUME SI PRODUSE CU NUMERE MARI 73
int k;
s=nrv(0);
for(k=0;k<=n-1;k++)
{
p=inm(comb(n-1,k),putere(n,n-1-k));
p=inm(p,factorial(k+1));
s=suma(s,p);
}
afisv(s);
}// main
static int[] nrv(int nr)
{
int nc,nrr=nr;
nc=0;
while(nr!=0) { nc++; nr=nr/10; }
int[] x=new int[nc];
nr=nrr;
nc=0;
while(nr!=0) { x[nc]=nr%10; nc++; nr=nr/10; }
return x;
}
static int[] inm(int[] x,int[] y)
{
int nx=x.length,ny=y.length;
int nz=nx+ny;
int[] z=new int[nz];
int[][] a=new int[ny][nz];
int i,j,t;
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
a[j][j+i]=y[j]*x[i]+t;
t=a[j][j+i]/10;
a[j][j+i]=a[j][j+i]%10;
}
a[j][j+i]=t;
}
t=0;
for(j=0;j<nz;j++)
74 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
{
z[j]=t;
for(i=0;i<ny;i++) z[j]=z[j]+a[i][j];
t=z[j]/10;
z[j]=z[j]%10;
}
if (z[nz-1]!=0) return z;
else
{
int[] zz=new int[nz-1];
for(j=0;j<nz-1;j++) zz[j]=z[j];
return zz;
}
}
static void afisv(int[]x)
{
int i;int n=x.length;
for(i=n-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] comb(int n,int k)
{
int i,j,d;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(i=1;i<=k;i++) y[i]=i;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(x[i],y[j]);
x[i]=x[i]/d;
y[j]=y[j]/d;
if(y[j]==1) break;
}
int[] p=nrv(1);
for(i=1;i<=k;i++) p=inm(p,nrv(x[i]));
return p;
}
static int cmmdc(int a,int b)
{
2.2. SUME SI PRODUSE CU NUMERE MARI 75
int d,i,c,r;
if(a>b) {d=a;i=b;}else {d=b;i=a;}
while(i!=0){c=d/i;r=d%i;d=i;i=r;}
return d;
}
static int[] putere(int a,int n)
{
int k;int[]p;
p=nrv(1);
for(k=1;k<=n;k++) p=inm(p,nrv(a));
return p;
}
static int[] factorial(int n)
{
int k;int[] p;
p=nrv(1);
for(k=1;k<=n;k++) p=inm(p,nrv(k));
return p;
}
static int[] suma(int[]x,int[]y)
{
int i,j,t;
int nx=x.length;
int ny=y.length;
int nz;
if(nx>ny) nz=nx+1; else nz=ny+1;
int[] z=new int[nz];
int[] xx=new int[nz];
int[] yy=new int[nz];
for(i=0;i<nx;i++) xx[i]=x[i];
for(i=0;i<ny;i++) yy[i]=y[i];
t=0;
for(i=0;i<nz;i++)
{
z[i]=xx[i]+yy[i]+t;
t=z[i]/10;
z[i]=z[i]%10;
}
if(z[nz-1]!=0) return z;
else
{
76 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
int[] zz=new int [nz-1];
for(i=0;i<nz-1;i++) zz[i]=z[i];
return zz;
}
}
}// class
2.2.4 Calcul f(n) = n
n1
+
n1
k=1
C
k
n
k
k1
(n k)
nk
cu numere
mari
class SP03NrMari
{
public static void main (String[]args)
{
int n;
int k;
int[] ss;
int[] pp;
for(n=10;n<=12;n++)
{
ss=nrv(0);
for(k=1;k<=n-1;k++)
{
pp=inm(comb(n,k),putere(k,k-1));
pp=inm(pp,putere(n-k,n-k));
ss=suma(ss,pp);
}
ss=suma(ss,putere(n,n-1));
System.out.print(n+" : ");
afisv(ss);
}
}
static int[] suma(int[] x, int[] y)
{
int i,j,t;
int ncx=x.length;
int ncy=y.length;
int ncz;
if(ncx>ncy) ncz=ncx+1; else ncz=ncy+1;
int[] xx=new int[ncz];
2.2. SUME SI PRODUSE CU NUMERE MARI 77
int[] yy=new int[ncz];
int[] z=new int[ncz];
for(i=0;i<ncx;i++) xx[i]=x[i];
for(j=0;j<ncy;j++) yy[j]=y[j];
t=0;
for(i=0;i<ncz;i++)
{
z[i]=xx[i]+yy[i]+t;
t=z[i]/10;
z[i]=z[i]%10;
}
if(z[ncz-1]!= 0) return z;
else
{
int[] zz=new int[ncz-1];
for(i=0;i<=ncz-2;i++) zz[i]=z[i];
return zz;
}
}
static int[] inm(int[]x,int[]y)
{
int t;
int n=x.length;
int m=y.length;
int i,j;
int[][] a=new int[m][n+m];
int[] z=new int[m+n];
for(j=0;j<m;j++)
{
t=0;
for(i=0;i<n;i++)
{
a[j][i+j]=y[j]*x[i]+t;
t=a[j][i+j]/10;
a[j][i+j]=a[j][i+j]%10;
}
a[j][i+j]=t;
}
t=0;
for(j=0;j<m+n;j++)
{
z[j]=0;
for(i=0;i<m;i++) z[j]=z[j]+a[i][j];
78 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
z[j]=z[j]+t;
t=z[j]/10;
z[j]=z[j]%10;
}
if(z[m+n-1]!= 0) return z;
else
{
int[] zz=new int[m+n-1];
for(i=0;i<=m+n-2;i++)
zz[i]=z[i];
return zz;
}
}
static void afisv(int[]x)
{
int i;
for(i=x.length-1;i>=0;i--) System.out.print(x[i]);
System.out.print(" ---> "+x.length+" cifre");
System.out.println();
}
static int[] nrv(int nr)
{
int nrrez=nr;
int nc=0;
while(nr!=0) { nc++; nr=nr/10; }
int[]x=new int [nc];
nr=nrrez;
nc=0;
while(nr!=0) { x[nc]=nr%10; nc++; nr=nr/10; }
return x;
}
static int[] putere (int a, int n)
{
int[] rez;
int k;
rez=nrv(1);
for(k=1;k<=n;k++) rez=inm(rez,nrv(a));
return rez;
}
static int[] comb (int n, int k)
2.2. SUME SI PRODUSE CU NUMERE MARI 79
{
int[] rez;
int i,j;
int d;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
rez=nrv(1);
for(i=1;i<=k;i++) rez=inm(rez,nrv(x[i]));
return rez;
}
static int cmmdc (int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else{d=b;i=a;}
while(i!=0){ c=d/i; r=d%i; d=i; i=r; }
return d;
}
}
2.2.5 Calcul f(m, n,
1
, ...,
n
) = (C
1
m
)
1
...
_
C
n
m+n1
_
n
cu numere
mari
class SP06NrMari
{
public static void main(String[] args)
{
int m=4;
int n=5;
int k;
int[] lam=new int[n+1];
int[] rez;
80 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
lam[1]=5;
lam[2]=6;
lam[3]=7;
lam[4]=8;
lam[5]=9;
rez=nr2v(1);
for(k=0;k<=n-1;k++)
rez=inm(rez,putere(comb(m+k,k+1),lam[k+1]));
afisv(rez);
}
static int[] putere(int[] a,int n)
{
int i;
int[] rez=nr2v(1);
for(i=1;i<=n;i++) rez=inm(rez,a);
return rez;
}
static int[] comb(int n,int k)
{
int i,j,d;
int[] rez;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
rez=nr2v(1);
for(i=1;i<=k;i++) rez=inm(rez,nr2v(x[i]));
return rez;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else {d=b;i=a;}
2.2. SUME SI PRODUSE CU NUMERE MARI 81
while (i!=0) { c=d/i; r=d%i; d=i; i=r; }
return d;
}
static int[] nr2v(int nr)
{
int nrr=nr,nc=0,i;
while(nr!=0) { nc++; nr=nr/10; }
int[] nrv=new int[nc];
nr=nrr;
for(i=0;i<nc;i++) { nrv[i]=nr%10; nr=nr/10; }
return nrv;
}
static int[] inm(int[]x, int[]y)
{
int nx=x.length, ny=y.length, i,j,t;
int[][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
a[j][i+j]=y[j]*x[i]+t;
t=a[j][i+j]/10;
a[j][i+j]=a[j][i+j]%10;
}
a[j][j+nx]=t;
}
t=0;
for(j=0;j<nx+ny;j++)
{
z[j]=0;
for(i=0;i<ny;i++) z[j]=z[j]+a[i][j];
z[j]=z[j]+t;
t=z[j]/10;
z[j]=z[j]%10;
}
if(z[nx+ny-1]!=0) return z;
else
{
int[] zz=new int[nx+ny-1];
for(i=0;i<nx+ny-1;i++) zz[i]=z[i];
82 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
return zz;
}
}
static void afisv(int[] x)
{
int i;
for(i=x.length-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
}
2.2.6 Numerele Stirling de spet a a II-a cu numere mari
Fie S(n, m) num arul modalit at ilor de partit ionare a unei mult imi cu n ele-
mente n m submult imi nevide (de exemplu, plasare numerelor {1, 2, ..., n} n m
cutii identice si nenumerotate astfel ncat nici o cutie s a nu e goala!). Acest num ar
ndeplineste urmatoarea relat ie de recurent a:
S(n + 1, m) = S(n, m) +mS(n, m) unde S(n, n) = S(n, 1) = 1.
Scriet i un program care s a calculeze, de exemplu, S(123, 45).
class SP09NrMari
{
public static void main(String[] args)
{
int n=123,m=45;
int i,j;
long t1,t2;
int[][][] a=new int[n+1][n+1][1];
t1=System.currentTimeMillis();
for(i=1;i<=n;i++) a[i][1]=nr2v(1);
for(i=1;i<=n;i++) a[i][i][0]=1;
for(i=3;i<=n;i++)
for(j=2;j<=min(m,i-1);j++)
a[i][j]=suma(a[i-1][j-1],inmnr(a[i-1][j],nr2v(j)));
afisv(a[n][m]);
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}
static int min(int a, int b){if(a<b) return a; else return b;}
2.2. SUME SI PRODUSE CU NUMERE MARI 83
static int[] suma(int[]x,int[]y)
{
int nx=x.length, ny=y.length, i,min,max,t;
if(nx>ny) { min=ny; max=nx; } else { min=nx; max=ny; }
int[] z=new int[max+1];
t=0;
for(i=0;i<min;i++){ z[i]=x[i]+y[i]+t; t=z[i]/10; z[i]=z[i]%10; }
for(i=min;i<max;i++)
{
if(nx>min) z[i]=x[i]+t; else z[i]=y[i]+t;
t=z[i]/10;
z[i]=z[i]%10;
}
z[max]=t;
if(z[max]!=0) return z;
else
{
int[] zz=new int[max];
for(i=0;i<max;i++) zz[i]=z[i];
return zz;
}
}
static int[] nr2v(int nr)
{
int nrrez=nr, nc;
int[] nrv;
nc=0;
while(nr!=0){ nc++; nr=nr/10; }
nrv=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0){ nrv[nc]=nr%10; nc++; nr=nr/10; }
return nrv;
}
static void afisv(int[]z)
{
int nz=z.length, i;
for(i=nz-1;i>=0;i--) System.out.print(z[i]);
System.out.println(" --> "+z.length);
}
static int[] inmnr(int[]x,int[]y)
84 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
{
int nx=x.length, ny=y.length, i,j,t,s;
int[] z=new int[nx+ny];
int[][] a=new int[ny][nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
a[j][i+j]=y[j]*x[i]+t;
t=a[j][i+j]/10;
a[j][i+j]=a[j][i+j]%10;
}
a[j][i+j]=t;
}
t=0;
for(j=0;j<nx+ny;j++)
{
s=0;
for(i=0;i<ny;i++) s=s+a[i][j];
s=s+t;
z[j]=s%10;
t=s/10;
}
if(z[nx+ny-1]!=0) return z;
else
{
int[] zz=new int[nx+ny-1];
for(j=0;j<nx+ny-1;j++) zz[j]=z[j];
return zz;
}
}
}//class
2.2.7 Numerele lui Bell cu numere mari
Fie B(n) num arul partit iilor unei mult imi nite cu n elemente n submult imi
nevide. Acest num ar ndeplineste urmatoarea relat ie de recurent a:
B(n + 1) =
n
k=0
C
k
n
B(k) unde B(0) = 1.
Scriet i un program care s a calculeze, de exemplu, B(71).
2.2. SUME SI PRODUSE CU NUMERE MARI 85
class SP10NrMari
{
public static void main(String[] args)
{
int n=71;
int k,i;
int[][] b=new int[n+1][1];
int[] prod={1};
b[0]=nr2v(1);
for(i=1;i<=n;i++)
{
b[i]=nr2v(0);;
for(k=0;k<=i-1;k++)
{
prod=inm(comb(i-1,k),b[k]);
b[i]=suma(b[i],prod);
}
System.out.print(i+" : ");
afisv(b[i]);
}
}
static int[] suma(int[] x,int[] y)
{
int nx=x.length;
int ny=y.length;
int nz;
if(nx>ny) nz=nx+1; else nz=ny+1;
int t,i;
int[] z=new int[nz];
int[] xx=new int[nz];
int[] yy=new int[nz];
for(i=0;i<nx;i++) xx[i]=x[i];
for(i=0;i<ny;i++) yy[i]=y[i];
t=0;
for(i=0;i<nz;i++)
{
z[i]=xx[i]+yy[i]+t;
t=z[i]/10;
z[i]=z[i]%10;
}
if(z[nz-1]!=0) return z;
else
{
86 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
int[] zz=new int[nz-1];
for(i=0;i<nz-1;i++) zz[i]=z[i];
return zz;
}
}
static int[] nr2v(int nr)
{
int nrr=nr,nc=0,i;
while(nr!=0) { nc++; nr=nr/10; }
int[] nrv=new int[nc];
nr=nrr;
for(i=0;i<nc;i++) { nrv[i]=nr%10; nr=nr/10; }
return nrv;
}
static int[] inm(int[]x, int[]y)
{
int nx=x.length, ny=y.length, i,j,t;
int[][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
a[j][i+j]=y[j]*x[i]+t;
t=a[j][i+j]/10; a[j][i+j]=a[j][i+j]%10;
}
a[j][j+nx]=t;
}
t=0;
for(j=0;j<nx+ny;j++)
{
z[j]=0;
for(i=0;i<ny;i++) z[j]=z[j]+a[i][j];
z[j]=z[j]+t;
t=z[j]/10;
z[j]=z[j]%10;
}
if(z[nx+ny-1]!=0) return z;
else
{
int[] zz=new int[nx+ny-1];
2.2. SUME SI PRODUSE CU NUMERE MARI 87
for(i=0;i<nx+ny-1;i++) zz[i]=z[i];
return zz;
}
}
static void afisv(int[]x)
{
int i;
for(i=x.length-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] comb(int n,int k)
{
int i,j,d;
int[] rez;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
rez=nr2v(1);
for(i=1;i<=k;i++) rez=inm(rez,nr2v(x[i]));
return rez;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else {d=b;i=a;}
while(i!=0) { c=d/i; r=d%i; d=i; i=r;}
return d;
}
}
88 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
2.2.8 Partit iile unui numar natural cu numere mari
Fie P(n, m) num arul modalit at ilor de partit ionare a num arului natural n ca
suma de m numere naturale far a a se t ine cont de ordinea acestora n suma (n
scrierea n = a
1
+a
2
+... +a
m
presupunem a
1
a
2
... a
m
1). Acest num ar
ndeplineste urmatoarea relat ie de recurent a:
P(n +k, k) = P(n, 1) +P(n, 2) +... +P(n, k) unde P(n, n) = P(n, 1) = 1.
Scriet i un program care s a calculeze, de exemplu, P(123, 45).
class SP11NrMari
{
public static void main(String[] args)
{
int n=123,m=45;
int[][][] p=new int[n+1][n+1][1];
int[] nsol;
int i,j,k;
p[1][1]=nr2v(1);
for(i=2;i<=n;i++)
{
p[i][i]=nr2v(1);
p[i][1]=nr2v(1);
for(j=2;j<i;j++)
{
p[i][j]=nr2v(0);
for(k=1;k<=j;k++) p[i][j]=suma(p[i][j],p[i-j][k]);
}
}
nsol=nr2v(0);
for(j=1;j<=n;j++) nsol=suma(nsol,p[n][j]);
System.out.print("nsol = "); afisv(nsol); System.out.println();
System.out.print("P("+n+","+m+") = ");afisv(p[n][m]); System.out.println();
}
static int[] suma(int[] x,int[] y)
{
int nx=x.length;
int ny=y.length;
int nz;
if(nx>ny) nz=nx+1; else nz=ny+1;
int t,i;
int[] z=new int[nz];
2.2. SUME SI PRODUSE CU NUMERE MARI 89
int[] xx=new int[nz];
int[] yy=new int[nz];
for(i=0;i<nx;i++) xx[i]=x[i];
for(i=0;i<ny;i++) yy[i]=y[i];
t=0;
for(i=0;i<nz;i++)
{
z[i]=xx[i]+yy[i]+t;
t=z[i]/10;
z[i]=z[i]%10;
}
if(z[nz-1]!=0) return z;
else
{
int[] zz=new int[nz-1];
for(i=0;i<nz-1;i++) zz[i]=z[i];
return zz;
}
}
static int[] nr2v(int nr)
{
int nrr=nr,nc=0,i;
while(nr!=0) { nc++; nr=nr/10; }
int[] nrv=new int[nc];
nr=nrr;
for(i=0;i<nc;i++) { nrv[i]=nr%10; nr=nr/10; }
return nrv;
}
static int[] inm(int[]x, int[]y)
{
int nx=x.length, ny=y.length, i,j,t;
int[][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
a[j][i+j]=y[j]*x[i]+t;
t=a[j][i+j]/10;
a[j][i+j]=a[j][i+j]%10;
}
90 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
a[j][j+nx]=t;
}
t=0;
for(j=0;j<nx+ny;j++)
{
z[j]=0;
for(i=0;i<ny;i++) z[j]=z[j]+a[i][j];
z[j]=z[j]+t;
t=z[j]/10;
z[j]=z[j]%10;
}
if(z[nx+ny-1]!=0) return z;
else
{
int[] zz=new int[nx+ny-1];
for(i=0;i<nx+ny-1;i++) zz[i]=z[i];
return zz;
}
}
static void afisv(int[]x)
{
int i;
for(i=x.length-1;i>=0;i--) System.out.print(x[i]);
System.out.print(" ");
}
static int min(int a, int b) { return (a<b)?a:b; }
}
2.2.9 Recurent a Catalan C
n
=
n
k=1
C
k1
C
nk
unde C
0
= 1,
cu numere mari
class SP12NrMari
{
public static void main(String[] args)
{
int n=123,i,k;
int[] p;
int[] s;
int[][] c=new int[n+1][1];
c[0]=nr2v(1);
2.2. SUME SI PRODUSE CU NUMERE MARI 91
for(i=1;i<=n;i++)
{
s=nr2v(0);
for(k=1; k<=i; k++)
{
p=inmnr(c[k-1],c[i-k]);
s=suma(s,p);
}
c[i]=s;
}
System.out.print("C("+n+") = "); afisv(c[n]);
}
static int[] suma(int[] x, int[] y)
{
int nx=x.length;
int ny=y.length;
int min,max,t,k;
if(nx>ny){ max=nx; min=ny; } else { max=ny; min=nx; }
int[] z=new int[max+1];
t=0;
for(k=0;k<min;k++)
{
z[k]=x[k]+y[k]+t;
t=z[k]/10;
z[k]=z[k]%10;
}
for(k=min;k<max;k++)
if(min<nx)
{
z[k]=x[k]+t;
t=z[k]/10;
z[k]=z[k]%10;
}
else if(min<ny) { z[k]=y[k]+t; t=z[k]/10; z[k]=z[k]%10;}
z[max]=t;
if(z[max]!=0) return z;
else
{
int[] zz=new int[max];
for(k=0;k<max;k++) zz[k]=z[k];
return zz;
}
92 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
}
static void afisv(int[] x)
{
int nx=x.length;
int i;
for(i=nx-1;i>=0;i--) System.out.print(x[i]);
System.out.println(" --> "+x.length+" cifre");
}
static int[] nr2v(int nr)
{
int nc;
int nrrez=nr;
nc=0;
while(nr!=0) {nc++; nr=nr/10;}
int[] x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0) { x[nc]=nr%10; nc++; nr=nr/10; }
return x;
}
static int[] inmnr(int[] x, int[] y)
{
int nx=x.length;
int ny=y.length;
int i,j,t,s;
int[] z=new int[nx+ny];
int[][] a=new int [ny][nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
a[j][i+j]=y[j]*x[i]+t;
t=a[j][i+j]/10;
a[j][i+j]=a[j][i+j]%10;
}
a[j][i+j]=t;
}
t=0;
for(j=0;j<nx+ny;j++)
{
2.2. SUME SI PRODUSE CU NUMERE MARI 93
s=0;
for(i=0;i<ny;i++) s=s+a[i][j];
s=s+t;
z[j]=s%10;
t=s/10;
}
if(z[nx+ny-1]!=0) return z;
else
{
int[] zz=new int[nx+ny-1];
for(i=0;i<nx+ny-1;i++) zz[i]=z[i];
return zz;
}
}
}
2.2.10 Recurent a: E
n
= E
2
E
n1
+ E
3
E
n2
+ ... + E
n1
E
2
unde
E
1
= E
2
= 1 cu numere mari
class SP13NrMari
{
public static void main(String[] args)
{
int n=118,i,k;
int[] p;
int[] s;
int[][] e=new int[n+1][1];
e[1]=nr2v(1);
e[2]=nr2v(1);
for(i=3;i<=n;i++)
{
s=nr2v(0);
for(k=2; k<=i-1; k++)
{
p=inmnr(e[k],e[i-k+1]);
s=suma(s,p);
}
e[i]=s;
System.out.print(i+" : "); afisv(e[i]);
}
}
94 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
static int[] suma(int[] x, int[] y)
{
int nx=x.length;
int ny=y.length;
int min,max,t,k;
if(nx>ny){max=nx;min=ny;}else{max=ny;min=nx;}
int[] z=new int[max+1];
t=0;
for(k=0;k<min;k++)
{
z[k]=x[k]+y[k]+t;
t=z[k]/10;
z[k]=z[k]%10;
}
for(k=min;k<max;k++)
if(min<nx)
{
z[k]=x[k]+t;
t=z[k]/10;
z[k]=z[k]%10;
}
else
if(min<ny)
{
z[k]=y[k]+t;
t=z[k]/10;
z[k]=z[k]%10;
}
z[max]=t;
if(z[max]!=0) return z;
else
{
int[] zz=new int[max];
for(k=0;k<max;k++) zz[k]=z[k];
return zz;
}
}
static void afisv(int[] x)
{
int nx=x.length;
int i;
for(i=nx-1;i>=0;i--) System.out.print(x[i]);
2.2. SUME SI PRODUSE CU NUMERE MARI 95
System.out.println(" --> "+x.length);
}
static int[] nr2v(int nr) // ok
{
int nc;
int nrrez=nr;
nc=0;
while(nr!=0) {nc++; nr=nr/10;}
int[] x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0)
{
x[nc]=nr%10;
nc++;
nr=nr/10;
}
return x;
}
static int[] inmnr(int[] x, int[] y)
{
int nx=x.length;
int ny=y.length;
int i,j,t,s;
int[] z=new int[nx+ny];
int[][] a=new int [ny][nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
a[j][i+j]=y[j]*x[i]+t;
t=a[j][i+j]/10;
a[j][i+j]=a[j][i+j]%10;
}
a[j][i+j]=t;
}
t=0;
for(j=0;j<nx+ny;j++)
{
s=0;
for(i=0;i<ny;i++) s=s+a[i][j];
96 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
s=s+t;
z[j]=s%10;
t=s/10;
}
if(z[nx+ny-1]!=0) return z;
else
{
int[] zz=new int[nx+ny-1];
for(i=0;i<nx+ny-1;i++) zz[i]=z[i];
return zz;
}
}
}
2.2.11 Calcul f(n) =
n
k=0
C
k
n
F
k
cu numere mari
class SP15NrMari
{
static int n=175;
static int[][] f=new int[n+1][1];
public static void main(String[] args)
{
int k,i;
f[0]=nr2v(0);
f[1]=nr2v(1);
f[2]=nr2v(1);
for(k=3;k<=n;k++) f[k]=suma(f[k-1],f[k-2]);
int[][] x=new int[n+1][1];
int[] prod={1};
for(i=1;i<=n;i++)
{
x[i]=nr2v(0);
for(k=0;k<=i;k++)
{
prod=inm(comb(i,k),f[k]);
x[i]=suma(x[i],prod);
}
System.out.print(i+" : "); afisv(x[i]);
}
}
2.2. SUME SI PRODUSE CU NUMERE MARI 97
static int[] suma(int[] x,int[] y)
{
int nx=x.length;
int ny=y.length;
int nz;
if(nx>ny) nz=nx+1; else nz=ny+1;
int t,i;
int[] z=new int[nz];
int[] xx=new int[nz];
int[] yy=new int[nz];
for(i=0;i<nx;i++) xx[i]=x[i];
for(i=0;i<ny;i++) yy[i]=y[i];
t=0;
for(i=0;i<nz;i++)
{
z[i]=xx[i]+yy[i]+t;
t=z[i]/10;
z[i]=z[i]%10;
}
if(z[nz-1]!=0) return z;
else
{
int[] zz=new int[nz-1];
for(i=0;i<nz-1;i++) zz[i]=z[i];
return zz;
}
}
static int[] nr2v(int nr)
{
int nrr=nr,nc=0,i;
while(nr!=0) { nc++; nr=nr/10; }
int[] nrv=new int[nc];
nr=nrr;
for(i=0;i<nc;i++) { nrv[i]=nr%10; nr=nr/10; }
return nrv;
}
static int[] inm(int[]x, int[]y)
{
int nx=x.length, ny=y.length, i,j,t;
int[][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
for(j=0;j<ny;j++)
98 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
{
t=0;
for(i=0;i<nx;i++)
{
a[j][i+j]=y[j]*x[i]+t;
t=a[j][i+j]/10;
a[j][i+j]=a[j][i+j]%10;
}
a[j][j+nx]=t;
}
t=0;
for(j=0;j<nx+ny;j++)
{
z[j]=0;
for(i=0;i<ny;i++) z[j]=z[j]+a[i][j];
z[j]=z[j]+t;
t=z[j]/10;
z[j]=z[j]%10;
}
if(z[nx+ny-1]!=0) return z;
else
{
int[] zz=new int[nx+ny-1];
for(i=0;i<nx+ny-1;i++) zz[i]=z[i];
return zz;
}
}
static void afisv(int[]x)
{
int i;
for(i=x.length-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] comb(int n,int k)
{
if(k>n/2) k=n-k; // o mica optimizare !
int i,j,d;
int[] rez;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
2.2. SUME SI PRODUSE CU NUMERE MARI 99
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
rez=nr2v(1);
for(i=1;i<=k;i++) rez=inm(rez,nr2v(x[i]));
return rez;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else {d=b;i=a;}
while (i!=0)
{
c=d/i;
r=d%i;
d=i;
i=r;
}
return d;
}
}
2.2.12 Calcul f(n) =
n
k=0
C
k
n
2
k
F
k
cu numere mari
class SP16NrMari
{
static int n=116;
static int[][] f=new int[n+1][1];
public static void main(String[] args)
{
int k,i;
f[0]=nr2v(0);
f[1]=nr2v(1);
f[2]=nr2v(1);
for(k=3;k<=n;k++) f[k]=suma(f[k-1],f[k-2]);
100 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
int[][] x=new int[n+1][1];
int[] prod={1};
for(i=1;i<=n;i++)
{
x[i]=nr2v(0);;
for(k=0;k<=i;k++)
{
prod=inm(comb(i,k),putere(2,k));
prod=inm(prod,f[k]);
x[i]=suma(x[i],prod);
}
System.out.print(i+" : "); afisv(x[i]);
}
}
static int[] suma(int[] x,int[] y)
{
int nx=x.length;
int ny=y.length;
int nz;
if(nx>ny) nz=nx+1; else nz=ny+1;
int t,i;
int[] z=new int[nz];
int[] xx=new int[nz];
int[] yy=new int[nz];
for(i=0;i<nx;i++) xx[i]=x[i];
for(i=0;i<ny;i++) yy[i]=y[i];
t=0;
for(i=0;i<nz;i++)
{
z[i]=xx[i]+yy[i]+t;
t=z[i]/10;
z[i]=z[i]%10;
}
if(z[nz-1]!=0) return z;
else
{
int[] zz=new int[nz-1];
for(i=0;i<nz-1;i++) zz[i]=z[i];
return zz;
}
}
2.2. SUME SI PRODUSE CU NUMERE MARI 101
static int[] nr2v(int nr)
{
int nrr=nr,nc=0,i;
while(nr!=0) { nc++; nr=nr/10; }
int[] nrv=new int[nc];
nr=nrr;
for(i=0;i<nc;i++) { nrv[i]=nr%10; nr=nr/10; }
return nrv;
}
static int[] inm(int[]x, int[]y)
{
int nx=x.length, ny=y.length, i,j,t;
int[][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
a[j][i+j]=y[j]*x[i]+t;
t=a[j][i+j]/10;
a[j][i+j]=a[j][i+j]%10;
}
a[j][j+nx]=t;
}
t=0;
for(j=0;j<nx+ny;j++)
{
z[j]=0;
for(i=0;i<ny;i++) z[j]=z[j]+a[i][j];
z[j]=z[j]+t;
t=z[j]/10;
z[j]=z[j]%10;
}
if(z[nx+ny-1]!=0) return z;
else
{
int[] zz=new int[nx+ny-1];
for(i=0;i<nx+ny-1;i++) zz[i]=z[i];
return zz;
}
}
102 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
static void afisv(int[]x)
{
int i;
for(i=x.length-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
static int[] comb(int n,int k)
{
if(k>n/2) k=n-k; // o mica optimizare !
int i,j,d;
int[] rez;
int[] x=new int[k+1];
int[] y=new int[k+1];
for(i=1;i<=k;i++) x[i]=n-k+i;
for(j=1;j<=k;j++) y[j]=j;
for(j=2;j<=k;j++)
for(i=1;i<=k;i++)
{
d=cmmdc(y[j],x[i]);
y[j]=y[j]/d;
x[i]=x[i]/d;
if(y[j]==1) break;
}
rez=nr2v(1);
for(i=1;i<=k;i++) rez=inm(rez,nr2v(x[i]));
return rez;
}
static int cmmdc(int a,int b)
{
int d,i,c,r;
if(a>b) {d=a;i=b;} else {d=b;i=a;}
while(i!=0) { c=d/i; r=d%i; d=i; i=r;}
return d;
}
static int[] putere(int a,int n)
{
int k;int[]p;
p=nr2v(1);
for(k=1;k<=n;k++) p=inm(p,nr2v(a));
return p;
}
2.2. SUME SI PRODUSE CU NUMERE MARI 103
}
2.2.13 Fract ie continua: determinarea fract iei init iale cu nu-
mere mari
class FractieContinua2NrMari
{
public static void main(String[] args)
{
int[] p,q;
int[] b={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25};
p=calcA(b);
q=calcB(b);
afisv(p); System.out.println("/"); afisv(q);
}
static int[] calcA(int[] b)
{
int n=b.length-1;
int[][] A=new int[b.length][1];
A[0]=nrv(b[0]);
A[1]=suma(nrv(b[0]*b[1]),nrv(1));
for(int k=2;k<=n;k++) A[k]=suma(produs(nrv(b[k]),A[k-1]),A[k-2]);
return A[n];
}
static int[] calcB(int[]b)
{
int n=b.length-1;
int[][] B=new int[b.length][1];
B[0]=nrv(1);
B[1]=nrv(b[1]);
for(int k=2;k<=n;k++) B[k]=suma(produs(nrv(b[k]),B[k-1]),B[k-2]);
return B[n];
}
static void afisv(int[] x)
{
int nx=x.length;
int i;
for(i=nx-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
104 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
}
static int[] nrv(int nr)
{
int nc;
int nrrez=nr;
nc=0;
while(nr!=0) {nc++; nr=nr/10;}
int[] x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0) { x[nc]=nr%10; nc++; nr=nr/10; }
return x;
}
static int[] suma(int[] x,int[] y)
{
int k,s,t;
int nx=x.length;
int ny=y.length;
int nz;
if(nx>ny)nz=nx+1; else nz=ny+1;
int[] z=new int[nz];
t=0;
for(k=0;k<nz;k++)
{
s=t;
if(k<nx) s=s+x[k];
if(k<ny) s=s+y[k];
z[k]=s%10;
t=s/10;
}
if(z[nz-1]!=0)return z;
else
{
int[]zz=new int[nz-1];
for(k=0;k<nz-1;k++) zz[k]=z[k];
return zz;
}
}
static int[] produs(int[] x,int[] y)
{
int i,j,t,s;
2.2. SUME SI PRODUSE CU NUMERE MARI 105
int nx=x.length;
int ny=y.length;
int nz=nx+ny;
int [][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
s=t+y[j]*x[i];
a[j][i+j]=s%10;
t=s/10;
}
a[j][i+j]=t;
}
t=0;
for(j=0;j<nz;j++)
{
s=0;
for(i=0;i<ny;i++) s=s+a[i][j];
s=s+t;
z[j]=s%10;
t=s/10;
}
if(z[nz-1]!=0)return z;
else
{
int[] zz=new int[nz-1];
for(j=0;j<zz.length;j++)
zz[j]=z[j];
return zz;
}
}
}//class
2.2.14 Numarul permutarilor idempotente, cu numere mari
import java.io.*; // numarul permutarilor idempotente p^2 = e in S_n
class PermIdempotenteNrMari
{
static int n;
106 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
public static void main(String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("n = "); n = Integer.parseInt(br.readLine());
int[][] np = new int[n+1][1];
np[0]=nr2v(1);
np[1]=nr2v(1);
for(int i=2;i<=n;i++)
{
np[i]=suma(np[i-1],inm(nr2v(i-1),np[i-2]));
System.out.print(i+" : "); afisv(np[i]);
}
}
static int[] suma(int[] x,int[] y)
{
int nx=x.length;
int ny=y.length;
int nz;
if(nx>ny) nz=nx+1; else nz=ny+1;
int t,i;
int[] z=new int[nz];
int[] xx=new int[nz];
int[] yy=new int[nz];
for(i=0;i<nx;i++) xx[i]=x[i];
for(i=0;i<ny;i++) yy[i]=y[i];
t=0;
for(i=0;i<nz;i++)
{
z[i]=xx[i]+yy[i]+t;
t=z[i]/10;
z[i]=z[i]%10;
}
if(z[nz-1]!=0) return z;
else
{
int[] zz=new int[nz-1];
for(i=0;i<nz-1;i++) zz[i]=z[i];
return zz;
}
}
static int[] nr2v(int nr)
2.2. SUME SI PRODUSE CU NUMERE MARI 107
{
int nrr=nr,nc=0,i;
while(nr!=0) { nc++; nr=nr/10; }
int[] nrv=new int[nc];
nr=nrr;
for(i=0;i<nc;i++) { nrv[i]=nr%10; nr=nr/10; }
return nrv;
}
static int[] inm(int[]x, int[]y)
{
int nx=x.length, ny=y.length, i,j,t;
int[][] a=new int[ny][nx+ny];
int[] z=new int[nx+ny];
for(j=0;j<ny;j++)
{
t=0;
for(i=0;i<nx;i++)
{
a[j][i+j]=y[j]*x[i]+t;
t=a[j][i+j]/10; a[j][i+j]=a[j][i+j]%10;
}
a[j][j+nx]=t;
}
t=0;
for(j=0;j<nx+ny;j++)
{
z[j]=0;
for(i=0;i<ny;i++) z[j]=z[j]+a[i][j];
z[j]=z[j]+t;
t=z[j]/10; z[j]=z[j]%10;
}
if(z[nx+ny-1]!=0) return z;
else
{
int[] zz=new int[nx+ny-1];
for(i=0;i<nx+ny-1;i++) zz[i]=z[i];
return zz;
}
}
static void afisv(int[]x)
{
int i;
108 CAPITOLUL 2. SIMULAREA OPERAT IILOR CU NUMERE MARI
for(i=x.length-1;i>=0;i--) System.out.print(x[i]);
System.out.println();
}
}
Capitolul 3
OJI 2002 clasa a IX-a
3.1 Poarta
Se considera harta universului ca ind o matrice cu 250 de linii si 250 de
coloane.
In ecare celula se g aseste o asa numita poarta stelar a, iar n anumite
celule se g asesc echipaje ale port ii stelare.
La o deplasare, un echipaj se poate deplasa din locul n care se aa n oricare
alt loc n care se g aseste o a doua poarta, n cazul nostru n orice alta pozit ie din
matrice.
Nu se permite situarea simultana a mai mult de un echipaj ntr-o celula. La
un moment dat un singur echipaj se poate deplasa de la o poarta stelar a la alta.
Cerint a
Dandu-se un num ar p (1 < p < 5000) de echipaje, pentru ecare echipaj ind
precizate pozit ia init iala si pozit ia nala, determinat i num arul minim de deplasari
necesare pentru ca toate echipajele s a ajunga din pozit ia init iala n cea nala.
Datele de intrare
Se citesc din sierul text poarta.in n urmatorul format:
pe prima linie num arul natural p reprezent and num arul de echipaje,
pe urmatoarele p linii cate 4 numere naturale, primele dou a reprezent and
coordonatele pozit iei init iale a unui echipaj (linie coloan a), urmatoarele dou a
reprezent and coordonatele pozit iei nale a aceluiasi echipaj (linie coloan a).
Datele de iesire
Pe prima linie a sierului text poarta.out se scrie un singur num ar reprezent and
num arul minim de deplasari necesar.
Restrict ii si precizari
coordonatele pozit iilor init iale si nale ale echipajelor sunt numere naturale
din intervalul [1, 250];
109
110 CAPITOLUL 3. OJI 2002 CLASA A IX-A
pozit iile init iale ale celor p echipaje sunt distincte dou a cate dou a;
pozit iile nale ale celor p echipaje sunt distincte dou a cate dou a.
Exemplu
poarta.in poarta.out
3 4
1 2 3 4
6 5 3 9
3 4 1 2
Timp maxim de executare: 1 secunda/test
3.1.1 Indicat ii de rezolvare - descriere solut ie *
Fie NrStationare num arul echipajelor stat ionare (care au pozit iile init iale
si nale egale) si NrCircuite num arul circuitelor grafului orientat format astfel:
nodurile sunt echipajele si exista arc de la echipajul i la echipajul j dac a si numai
dac a pozit ia nala a echipajului i coincide cu pozit ia init iala a echipajului j.
Atunci NrMinDeplasari=p+NrCircuite-NrStationare.
3.1.2 Rezolvare detaliata
3.1.3 Codul sursa *
import java.io.*;
class Poarta
{
static int p,nmd,nc=0,ns=0;
static int[] xi,yi,xf,yf;
static boolean[] ea; // EsteAnalizat deja
3.1. POARTA 111
public static void main(String[] args) throws IOException
{
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("poarta10.in")));
st.nextToken(); p=(int)st.nval;
xi=new int[p+1];
yi=new int[p+1];
xf=new int[p+1];
yf=new int[p+1];
ea=new boolean[p+1]; // implicit este false
int i;
for(i=1;i<=p;i++)
{
st.nextToken(); xi[i]=(int)st.nval;
st.nextToken(); yi[i]=(int)st.nval;
st.nextToken(); xf[i]=(int)st.nval;
st.nextToken(); yf[i]=(int)st.nval;
}
for(i=1;i<=p;i++)
{
if(ea[i]) continue;
if((xf[i]==xi[i])&&(yf[i]==yi[i])) { ea[i]=true; ns++;}
else if(circuit(i)) nc++;
}
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("poarta.out")));
nmd=p+nc-ns;
System.out.println(p+" "+nc+" "+ns+" "+nmd);
out.print(nmd);
out.close();
}
static boolean circuit(int i)
{
int j=succesor(i);
while((j!=-1)&&(j!=i))
{
ea[j]=true;
j=succesor(j);
}
if(j==i) return true; else return false;
}
112 CAPITOLUL 3. OJI 2002 CLASA A IX-A
static int succesor(int j) // j --> k
{
int k;
for(k=1;k<=p;k++)
if((xf[j]==xi[k])&&(yf[j]==yi[k])) return k;
return -1;
}
}
3.2 Mouse
Un experiment urmareste comportarea unui soricel pus ntr-o cutie dreptun-
ghiular a, mpart it a n m n camarut e egale de forma patrata. Fiecare camarut a
cont ine o anumita cantitate de hrana.
Soricelul trebuie s a porneasc a din colt ul (1, 1) al cutiei si s a ajunga n colt ul
opus, manc and cat mai mult a hrana. El poate trece dintr-o cameran una al aturata
(doua camere sunt al aturate dac a au un perete comun), mananc a toata hrana din
camarut a atunci cand intra si nu intra niciodata ntr-o camera far a hrana.
Cerint a
Stabilit i care este cantitatea maxima de hrana pe care o poate manca si
traseul pe care l poate urma pentru a culege aceast a cantitate maxima.
Datele de intrare
Fisierul de intrare mouse.in cont ine pe prima linie dou a numere m si n
reprezent and num arul de linii respectiv num arul de coloane ale cutiei, iar pe
urmatoarele m linii cele m n numere reprezent and cantitatea de hrana exis-
tent a n ecare camarut a, cate n numere pe ecare linie, separate prin spat ii.
Toate valorile din sier sunt numere naturale ntre 1 si 100.
Datele de iesire
Imp art irea se realizeaza punand num arul maxim posibil de cuvinte pe ecare
linie, far a mpart irea cuvintelor n silabe.
Pentru aliniere stanga-dreapta, Vasile trebuie s a repartizeze spat ii n mod
uniform ntre cuvintele de pe ecare linie, astfel ncat ultimul caracter de pe
linie s a e diferit de spat iu, iar num arul total de caractere de pe linie s a e egal
cu Max. Except ie face numai ultima linie din paragraf, care r amane aliniata la
stanga (cuvintele ind separate printr-un singur spat iu, chiar dac a linia nu este
plina).
Intre Ion si are exista 2 spat ii, ntre are si multe - 2 spat ii, iar ntre multe
si pere - 1 spat iu.
Observat i ca paragraful Ana are mere. (care are lungimea mai mica decat
20) a r amas aliniat la stanga, iar ultima linie din ecare paragraf r amane aliniata
la stanga, cuvintele consecutive ind separate printr-un singur spat iu.
Timp maxim de executare: 1 secunda/test.
4.1.1 Indicat ii de rezolvare - descriere solut ie *
Fiecare paragraf se preia ntr-un vector de string-uri, elementele vectorului
cont inand cuvintele din paragraf. Se parcurge acest vector, ncepand cu prima
pozit ie, determin and cel mai mare indice i
1
care permite plasarea cuvintelor de pe
pozit iile 1, ..., i
1
pe acelasi r and. Se destribuie spat iile disponibile, conform cerint ei
problemei si se aseaza aceast a linie. Se continua prelucrarea vectorului ncepand
cu pozit ia i
1
+ 1, si asa mai departe!
4.1. TEXT 119
4.1.2 Rezolvare detaliata *
21
E cerul sus
Ca niste-ntinse brate
N-au crengile de ce sa se agate
0000:0000 32 31 0D 0A 45 20 63 65 72 75 6C 20 73 75 73 0D
0000:0010 0A 43 61 20 6E 69 73 74 65 2D 6E 74 69 6E 73 65
0000:0020 20 62 72 61 74 65 0D 0A 4E 2D 61 75 20 63 72 65
0000:0030 6E 67 69 6C 65 20 64 65 20 63 65 20 73 61 20 73
0000:0040 65 20 61 67 61 74 65 0D 0A 1A
Sf arsitul de sier (EOF) este marcat prin 1A.
Sf arsitul de linie (EOL) este marcat prin 0D0A.
4.1.3 Codul sursa *
import java.io.*;
class Text
{
static int Max, nc;
static String[] s=new String[501]; // cuvintele din paragraf
static int[] lgc=new int[501]; // numarul caracterelor cuvintelor
static int[] nsp=new int[501]; // numarul spatiilor dupa cuvant
static int cs=0, cd=0; // cs=cuvant stanga, cd=cuvant dreapta
static int lglin=0;
static PrintWriter out;
public static void main(String[] args) throws IOException
{
out=new PrintWriter(new BufferedWriter(new FileWriter("text.out")));
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("text.in")));
st.eolIsSignificant(true);
st.nextToken(); Max=(int)st.nval;
st.nextToken(); // preia EOL-ul existent dupa Max
while(st.nextToken()!=StreamTokenizer.TT_EOF)
{
nc=0;
120 CAPITOLUL 4. OJI 2003 CLASA A IX-A
do
{
s[++nc]=st.sval.toString();
} while(st.nextToken()!=StreamTokenizer.TT_EOL);
rezolva();
}
out.close();
}
static void rezolva() throws IOException
{
cs=0; // primul cuvant din linie (din stanga)
cd=0; // ultimul cuvant din linie (din stanga)
while(cd<nc)
{
cs=cd+1;
cd=cs;
lglin=s[cs].length();
while((cd+1<=nc)&&(lglin+1+s[cd+1].length()<=Max))
{
cd++;
lglin=lglin+1+s[cd].length();
}
if(cd<nc) unRand(); else ultimulRand();
}
}
static void unRand() throws IOException
{
int i,j;
int ntsr; // ntsr=nr total de spatii ramase de distribuit
int nsr; // nsr=nr spatii ramase de distribuit pentru primele cuvinte
int nsf; // nr spatii de adaugat dupa fiecare cuvant cs ... cd-1
ntsr=Max-lglin;
if(cs!=cd)
{
nsf=ntsr/(cd-cs);
nsr=ntsr%(cd-cs);
for(i=cs;i<cd;i++) nsp[i]=1+nsf;
for(i=1;i<=nsr;i++) nsp[cs+i-1]++;
for(i=cs;i<=cd-1;i++)
{
out.print(s[i]);
4.2. NUMERE 121
for(j=1;j<=nsp[i];j++) out.print(" ");
}
out.println(s[cd]);
}
}
static void ultimulRand() throws IOException
{
int i;
out.print(s[cs]);
for(i=cs+1;i<=cd;i++) out.print(" "+s[i]);
out.println();
}
}
4.2 Numere
Gigel este un mare pasionat al cifrelor. Orice moment liber si-l petrece jucandu-
se cu numere.
Juc andu-se astfel, ntr-o zi a scris pe hartie 10 numere distincte de cate dou a
cifre si a observat ca printre acestea exista dou a submult imi disjuncte de suma
egal a.
Desigur, Gigel a crezut ca este o nt amplare si a scris alte 10 numere dis-
tincte de cate dou a cifre si spre surpriza lui, dupa un timp a g asit din nou dou a
submult imi disjuncte de suma egal a.
Cerint a
Date 10 numere distincte de cate dou a cifre, determinat i num arul de perechi
de submult imi disjuncte de suma egal a care se pot forma cu numere din cele
date, precum si una dintre aceste perechi pentru care suma numerelor din ecare
dintre cele dou a submult imi este maxima.
Date de intrare
Fisierul de intrare numere.in cont ine pe prima linie 10 numere naturale
distincte separate prin cate un spat iu x
1
x
2
... x
10
.
Date de iesire
Fisierul de iesire numere.out cont ine trei linii. Pe prima linie se aa num arul
de perechi de submult imi de suma egal a, precum si suma maxima obt inuta, sepa-
rate printr-un spat iu. Pe linia a doua se aa elementele primei submult imi, iar pe
linia a treia se aa elementele celei de a doua submult imi, separate prin cate un
spat iu.
122 CAPITOLUL 4. OJI 2003 CLASA A IX-A
NrSol Smax NrSol - num arul de perechi; Smax - suma maxima
x
1
... x
k
elementele primei submult imi
y
1
... y
p
elementele celei de a doua submult imi
Restrict ii si precizari
10 x
i
, y
i
99, pentru 1 i 10.
1 k, p 9.
Ordinea submult imilor n perechi nu conteaza.
Perechea de submult imi determinata nu este obligatoriu unic a.
Exemplu
numere.in numere.out
60 49 86 78 23 97 69 71 32 10 130 276
78 97 69 32
60 49 86 71 10
Explicat ie:
130 de solut ii; suma maxima este 276; s-au folosit 9 din cele 10 numere; prima
submult ime are 4 elemente, a doua are 5 elemente.
Timp maxim de executare: 1 secunda/test
4.2.1 Indicat ii de rezolvare - descriere solut ie *
Numarul mic al numerelor (numai 10 numere distincte) permite generarea
tuturor submult imilor, vericarea condit iilor din problema pentru ecare pereche
de submult imi si determinarea informat iilor cerute.
4.2.2 Rezolvare detaliata
4.2.3 Codul sursa *
import java.io.*;
class Numere
{
static int[] x=new int[10];
static PrintWriter out;
public static void main(String[] args) throws IOException
{
int i, ia, ib, nsol=0, smax=-1, iamax=123,ibmax=123, sumaia=-1;
long t1,t2;
4.2. NUMERE 123
t1=System.currentTimeMillis();
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("numere.in")));
out=new PrintWriter(new BufferedWriter(new FileWriter("numere.out")));
for(i=0;i<10;i++) {st.nextToken(); x[i]=(int)st.nval;}
for(ia=1;ia<=1022;ia++)
for(ib=ia+1;ib<=1022;ib++) // fara ordine intre A si B
if((ia&ib)==0)
{
sumaia=suma(ia);
if(sumaia==suma(ib))
{
nsol++;
if(sumaia>smax)
{
smax=sumaia;
iamax=ia;
ibmax=ib;
}
}
}
out.println(nsol+" "+smax);
afis(iamax);
afis(ibmax);
out.close();
t2=System.currentTimeMillis();
System.out.println(t2-t1);
}// main
static int suma(int i)
{
int s=0,k=0;
for(k=0;k<=9;k++) if( (i&(1<<k)) != 0 ) s+=x[k];
return s;
}
static void afis(int i)
{
int k=0;
while(i!=0)
{
if(i%2!=0) out.print(x[k]+" ");
k++;
i/=2;
124 CAPITOLUL 4. OJI 2003 CLASA A IX-A
}
out.println();
}
}// class
Capitolul 5
OJI 2004 clasa a IX-a
5.1 Expresie
Se da un sir de n numere naturale nenule x
1
, x
2
, ..., x
n
si un num ar natural
m.
Cerint a
Sa se verice dac a valoarea expresiei
m
x
1
...x
n
exte un num ar natural.
30000).
Citirea datelor, vericarea dac a expresia este un num ar natural si asarea au
ordinul de complexitate O(n).
30000.
5.1. EXPRESIE 127
5.1.2 Rezolvare detaliata
5.1.3 Codul sursa *
Prima variant a:
import java.io.*;
class Expresie1
{
static int[] p=new int[30000];
static int m,n;
public static void main(String[] args) throws IOException
{
int i;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("expresie.in")));
st.nextToken(); m=(int)st.nval;
st.nextToken(); n=(int)st.nval;
int[] x=new int[n+1];
for(i=1;i<=n;i++) { st.nextToken(); x[i]=(int)st.nval; }
for(i=1;i<=n;i++) descfact(x[i]);
int ok=1;
for (i=2;i<30000;i++)
if (p[i]%m==0) p[i]=p[i]/m;
else { ok=0; break; }
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("expresie.out")));
if(ok==0) out.println(0);
else
{
out.println(1);
for(i=2;i<30000;i++)
if(p[i]!=0) out.println(i+" "+p[i]);
}
out.close();
}
static void descfact(int nr)
{
int d=2;
while(nr%d==0)
128 CAPITOLUL 5. OJI 2004 CLASA A IX-A
{
p[d]++;
nr=nr/d;
}
d=3;
while(d<=nr)
{
while(nr%d==0) { p[d]++; nr=nr/d; }
d=d+2;
}
}
}
A doua variant a:
import java.io.*;
class Expresie2 // pentru valori < 30.000 sunt 3245 prime 2...29.989
{ // sunt ~10% numere prime (+/- 5%)
static final int valmax=30000; // valoare maxima pentru x_i
static int m,n,nnp; // nnp=nr numere prime < valmax
static int[] x;
static int[] p=new int[3246]; // numere prime
static int[] e=new int[3246]; // exponenti corespunzatori
static boolean ok;
public static void main(String[] args) throws IOException
{
int i,j;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(
new FileReader("expresie.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(
new FileWriter("expresie.out")));
st.nextToken(); m=(int)st.nval;
st.nextToken(); n=(int)st.nval;
x=new int[n+1];
for(i=1;i<=n;i++) { st.nextToken(); x[i]=(int)st.nval; }
sol();
if(!ok) out.println(0);
else
{
out.println(1);
for(i=1;i<=nnp;i++)
if(e[i]>0) out.println(p[i]+" "+e[i]);
5.1. EXPRESIE 129
}
out.close();
}// main
static void sol()
{
int i,j;
prime(); // afisv(p);
for(i=1;i<=nnp;i++) e[i]=0; // era initializat implicit !!!
for(i=1;i<=n;i++)
{
j=1; // pozitie in lista numerelor prime p[]
while(x[i]!=1)
{
while(x[i]%p[j]==0) { e[j]++; x[i]/=p[j]; }
j++;
}
}
ok=true;
for(i=1;i<=nnp;i++)
if(e[i]%m==0) e[i]=e[i]/m; else {ok=false; break;}
}
static void prime()
{
int i,j;
p[1]=2; p[2]=3; nnp=2;
i=5;
while(i<valmax)
{
if(estePrim(i)) p[++nnp]=i;
i+=2;
}
}
static boolean estePrim(int nr) // folosind lista numerelor prime !
{
int i=1;
while((p[i]*p[i]<nr)&&(nr%p[i]!=0)) i++;
if(p[i]*p[i]>nr) return true; return false;
}
}
A treia variant a:
130 CAPITOLUL 5. OJI 2004 CLASA A IX-A
import java.io.*;
class Expresie3 // pentru "peste 5.000 de factori"
{
static int m,n,nf=0,nfc;
static int[] x;
static int[] f={}, e={};
static int[] fc=new int[6]; // 2*3*5*7*11*13=30030 > 30000 pentru x[i]
static int[] ec=new int[6]; // exponenti curenti corespunzatori
static boolean ok;
public static void main(String[] args) throws IOException
{
int i,j;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(
new FileReader("Expresie.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(
new FileWriter("Expresie.out")));
st.nextToken(); m=(int)st.nval;
st.nextToken(); n=(int)st.nval;
x=new int[n];
for(i=0;i<n;i++) { st.nextToken(); x[i]=(int)st.nval; }
sol();
if(!ok) out.println(0);
else
{
out.println(1);
for(i=0;i<nf;i++) out.println(f[i]+" "+e[i]);
}
out.close();
}// main
static void sol()
{
int i;
for(i=0;i<n;i++)
{
if(x[i]==1) continue;
descfact(x[i]); interclasare();
}
ok=true;
for(i=0;i<nf;i++)
if(e[i]%m==0) e[i]=e[i]/m; else {ok=false; break;}
5.1. EXPRESIE 131
}
static void interclasare() // (f cu ff) SI (e cu ee)
{
int i;
if(nf==0)
{
int[] ff=new int[nfc], ee=new int[nfc];
for(i=0;i<nfc;i++) {ff[i]=fc[i]; ee[i]=ec[i];}
f=ff; e=ee; nf=nfc; return;
}
int j, nft=nf+nfc,n;
int[] ff=new int[nft], ee=new int[nft];
i=0; j=0; n=0; // primul indice in care incarc este 0=zero !!!
while((i<nf)&&(j<nfc))
{
n++;
if(f[i]<fc[j])
{
ff[n-1]=f[i];
ee[n-1]=e[i];
i++;
}
else if(f[i]>fc[j])
{
ff[n-1]=fc[j];
ee[n-1]=ec[j];
j++;
}
else
{
ff[n-1]=f[i];
ee[n-1]=e[i]+ec[j];
i++; j++;
}
}
while(i<nf) {n++; ff[n-1]=f[i]; ee[n-1]=e[i]; i++;}
while(j<nfc) {n++; ff[n-1]=fc[j]; ee[n-1]=ec[j]; j++;}
if(n==nft) {f=ff; e=ee; nf=n;}
else
{
int[] fff=new int[n], eee=new int[n];
for(i=0;i<n;i++) {fff[i]=ff[i]; eee[i]=ee[i];}
f=fff; e=eee; nf=n;}
132 CAPITOLUL 5. OJI 2004 CLASA A IX-A
}
static void descfact(int nr)
{
// if((nr==0)||(nr==1)) return nr;
nfc=0;
int d=2;
if(nr%d==0)
{
nfc++; fc[nfc-1]=d; ec[nfc-1]=0;
while(nr%d==0) {ec[nfc-1]++; nr=nr/d;}}
d=3;
while((d*d<=nr)&&(nr!=1))
{
if(nr%d==0)
{
nfc++;
fc[nfc-1]=d;
ec[nfc-1]=0;
while(nr%d==0) {ec[nfc-1]++; nr=nr/d;}
}
d=d+2;
}
if(nr!=1) {nfc++; fc[nfc-1]=nr; ec[nfc-1]=1;}
}// descfact
}//class
5.2 Reactivi
In cadrul unui pas, determinarea intervalului care se termina cel mai repede,
pe baza vectorului sortat, are ordinul de complexitate O(1). Eliminarea intervalelor
care cont in un anumit punct (sf arsitul intervalului care se termina cel mai repede)
are ordinul de complexitate O(N).
Asarea rezultatului are ordinul de complexitate O(1).
In nal se va asa prima valoare x care are cel mai mare num ar de divizori,
precum si valoarea contorului.
6.2.2 Rezolvare detaliata
6.2.3 Codul sursa *
Varianta 1:
import java.io.*; //timp = 5600
class MaxD
{
static int[] x;
static int a,b;
public static void main(String[] args) throws IOException
{
142 CAPITOLUL 6. OJI 2005 CLASA A IX-A
int i;
long t1,t2;
t1=System.currentTimeMillis();
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("maxd.in")));
st.nextToken(); a=(int)st.nval;
st.nextToken(); b=(int)st.nval;
x=new int[b-a+2];
for(i=a;i<=b;i++) x[i-a+1]=descfact(i);
int max=-1;
int imax=-1;
for(i=1;i<=b-a+1;i++)
if(x[i]>max) { max=x[i]; imax=i; }
int nrmax=0;
for(i=1;i<=b-a+1;i++) if(x[i]==max) nrmax++;
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("maxd.out")));
out.println((imax+a-1)+" "+max+" "+nrmax);
out.close();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}
static int descfact(int nr)
{
int d;
int nrd;
int p=1;
d=2;
nrd=0;
while(nr%d==0) { nrd++; nr=nr/d; }
p=p*(nrd+1);
d=3;
while(d*d<=nr)
{
nrd=0;
while(nr%d==0) { nrd++; nr=nr/d; }
p=p*(nrd+1);
d=d+2;
}
if(nr>1) p*=2;
6.2. MAXD 143
return p;
}
}
Varianta 2:
import java.io.*;
class MaxD
{
public static void main(String[] args) throws IOException
{
int i;
int a,b;
long t1,t2;
t1=System.currentTimeMillis();
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("maxd.in")));
st.nextToken(); a=(int)st.nval;
st.nextToken(); b=(int)st.nval;
int max=-1;
int imax=-1;
int nrmax=0;
int nd;
for(i=a;i<=b;i++)
{
nd=nrDiv(i);
if(nd>max) {max=nd; imax=i; nrmax=1;}
else if(nd==max) nrmax++;
}
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("maxd.out")));
out.println(imax+" "+max+" "+nrmax);
out.close();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}// main(...)
144 CAPITOLUL 6. OJI 2005 CLASA A IX-A
static int nrDiv(int nr)
{
int d;
int nrd;
int p=1;
d=2;
nrd=0;
while(nr%d==0) { nrd++; nr=nr/d; }
p=p*(nrd+1);
d=3;
while(d*d<=nr)
{
nrd=0;
while(nr%d==0) { nrd++; nr=nr/d; }
p=p*(nrd+1);
d=d+2;
}
if(nr>1) p*=2;
return p;
}// nrDiv(...)
}// class
Capitolul 7
OJI 2006 clasa a IX-a
7.1 Flori
Cristina Bohm
Fetit ele din grupa mare de la gr adinit a culeg ori si vor s a mpleteasc a
coronit e pentru festivitatea de premiere.
In gr adina sunt mai multe tipuri de ori.
Fiecare dintre cele n fetit e culege un buchet av and acelasi num ar de ori, ns a nu
neaparat de acelasi tip. Pentru a mpleti coronit ele fetit ele se mpart n grupe. O
fetit a se poate atasa unui grup numai dac a are cel put in o oare de acelasi tip cu
cel put in o alta fetit a din grupul respectiv.
Cerint a
Fiind dat un num ar natural n reprezent and num arul fetit elor si num arul
natural k reprezent and num arul de ori dintr-un buchet, s a se determine grupele
care se formeaz a.
Date de intrare
Fisierul de intrare ori.in cont ine pe prima linie, separate printr-un spat iu,
numerele naturale n si k, reprezent and num arul de fetit e si respectiv num arul de
ori din ecare buchet. Fiecare dintre urmatoarele n linii cont ine, pentru ecare
fetit a, cate k valori separate prin cate un spat iu reprezent and tipurile de ori
culese.
Date de iesire
Fisierul de iesire ori.out va cont ine pe ecare linie cate o grupa format a din
numerele de ordine ale fetit elor separate prin cate un spat iu, n ordine cresc atoare,
ca n exemplu.
Restrict ii si precizari
1 n 150
1 k 100
Tipul unei ori este un num ar ntreg din intervalul [0, 100].
145
146 CAPITOLUL 7. OJI 2006 CLASA A IX-A
Intr-o grupa numerele de ordine ale fetit elor trebuie date n ordine strict
crescatoare.
In timpul act iunii Furtun a n desert din cauza unei furtuni de nisip, n
soldat i s-au r at acit de plutoanele lor. Dup a trecerea furtunii se pune problema
regruparii acestora pe plutoane. Pentru aceasta se folosesc placut ele de identicare
pe care soldat ii le poarta la g at. Pe aceste placut e sunt scrise numere care pot
identica ecare soldat si plutonul din care acesta face parte. Astfel, soldat ii din
acelasi pluton au num arul de identicare format din aceleasi cifre, dispuse n alta
ordine si numerele de identicare sunt unice. De exemplu, numerele de identicare
78003433, 83043073, 33347008 indic a faptul ca cei trei soldat i care le poarta fac
parte din acelasi pluton.
Cerint a
Fiind date cele n numere de pe placut ele de identicare, s a se regrupeze cei
n soldat i pe plutoane, indic andu-se num arul de plutoane g asite (un pluton refacut
trebuie s a aiba minimum un soldat), num arul de soldat i din cel mai numeros
pluton, num arul de plutoane care au acest num ar maxim de soldat i precum si
component a unui astfel de pluton (cu num ar maxim de soldat i regrupat i).
Date de intrare
Fisierul de intrare pluton.in cont ine pe prima linie num arul n de soldat i
recuperat i, iar pe ecare dintre urmatoarele n linii cate un num ar de identicare
a celor n soldat i.
Date de iesire
Fisierul de iesire pluton.out va cont ine pe prima linie num arul de plutoane
refacute. Linia a doua va cont ine num arul de soldat i din cel mai numeros pluton
refacut. Linia a treia va cont ine num arul de plutoane care au num arul maxim
de soldat i recuperat i. Linia a patra va cont ine component a unui astfel de pluton,
cu num ar maxim de soldat i recuperat i, numerele de identicare ale soldat ilor din
component a ind scrise unul dupa altul separate prin cate un spat iu.
Restrict ii si precizari
0 < n 4000
0 < num ar de identicare < 2.000.000.000
Observat ii
Deoarece linia a patra cont ine numerele de identicare ale soldat ilor unuia
dintre plutoanele cu un num ar maxim de soldat i, pot exista mai multe solut ii
corecte. Se poate alege oricare dintre acestea.
Se acorda punctaje part iale astfel: pentru valoarea corecta de pe prima linie
se acorda 30% din punctaj; pentru valorile corecte de pe prima si a doua linie se
acorda 50% din punctaj, pentru valorile corecte de pe prima, a doua si a treia linie
se acorda 70% din punctaj, iar pentru rezolvarea corecta a tuturor cerint elor se
acorda punctajul integral aferent testului.
7.2. PLUTON 151
Exemplu
pluton.in pluton.out Explicat ie
10 6 Au fost recuperat i soldat i din 6 plutoane
1223 3 distincte, cei mai mult i soldat i recuperat i
123 2 dintr-un pluton ind n num ar de 3.
666 321 312 123
321 Exist a 2 plutoane cu num ar maxim de
7890 soldat i recuperat i (3), unul dintre ele
2213 ind format din soldat ii cu numerele
312 321 312 123.
655
1000 De remarcat ca si solut ia
1322 1223 2213 1322 este corecta.
Timp de rulare/test: 1 secunda
7.2.1 Indicat ii de rezolvare - descriere solut ie *
Solut ia comisiei
Solut ia 1:
n timpul citirii creez un nou vector care cont ine pe pozit iile corespunzatoare
numerele de identicare din vectorul init ial n ordinea descrescatoare a cifrelor
n etapa a doua se parcurge vectorul nou format grupand toate numerele
de identicare identice; dupa formarea unui grup (pluton) se determin a marimea
acestuia ret inadu-se acesta dac a e cel mai numeros g asit pana n acel moment
sau contorizandu-l dac a num arul de soldat i determinat este egal cu cel maxim
determinat anterior.
Solut ia 2:
citesc numerele de identicare n vectorul a[]
construiesc 2 vectori ajut atori
vectorul b[] care va cont ine num arul de cifre al ecarui element
vectorul c[] care va cont ine num arul de cifre distincte a ecarui element
ordonez cei trei vectori crescator dupa num arul de cifre distincte (dupa c[])
si dupa num arul de cifre, deci cheia de sortare va un num ar construit dupa
formula c[i]*10+b[i]
formez si num ar plutoanele; plutoanele le voi ret ine pe linii distincte a ma-
tricei G[MAX][2]
n ecare linie, elementul G[i][0] va cont ine num arul de elemente din
pluton
152 CAPITOLUL 7. OJI 2006 CLASA A IX-A
elementul G[i][1] va cont ine reprezentantul plutonului, primul care
apare n a[]
repet pana cand toate elementele din a au fost vericate
ret inem primul element nepus nca din pluton cu caracteristicile lui
veric elementele cu aceleasi caracteristici s a fac a parte din acelasi
pluton cu primul element din pluton pe care l-am ret inut
testez dac a are aceleasi cifre
dac a nu are aceleasi cifre trec mai departe
altfel l numar (nca face parte din acelasi pluton)
detectez num arul maxim de elemente ale unui pluton si ret in maximul
asare cerint ele 1 2 3 folosind valorile aate
la cerint a 4
caut in a[] reprezentantul unui pluton numeros
asez cele maxe elemente - n vectorul sortat elementele cu aceleasi
caracteristici (b si c) sunt unul dupa altul, dar mai trebuie vericat
s a aiba caracteristicile reprezentantului (ex. 1212 si 3434 au aceleasi
caracteristici (4,2), (4,2), dar nu fac parte din acelasi pluton)
Solut ia 3:
se utilizeaza notiunea de lista: dintr-o lista fac parte toti membrii unui pluton
se construieste un vector ajutator care retine pentru ecare element elemen-
tul care il urmeaza in lista
pe parcursul formarii listelor se determina lista cea mai numeroasa precum
si numarul de liste de acest tip
asarea se face utilizand informatiile din vetorul urm
7.2.2 Rezolvare detaliata
7.2.3 Codul sursa *
Solutie incorecta pentru Borland C++ 3.1 dar care ia 100 puncte !!!
7.2. PLUTON 153
import java.io.*;
class Pluton1
{
static int n,np;
static long[] ni=new long[4001];
static long[] nid=new long[4001];
static int[] nip=new int[4001];
static int[] z=new int[4001];
static int[] fc=new int[10];
static int[] x=new int[11];
static long cifre(long nr) // 1230456789 --> 9.876.543.210 !!!
{
int i,j,k,nc=0;
long nrcd=0; // nr cu cifre descrescatoare
for(i=0;i<=9;i++) fc[i]=0;
for(i=0;i<=10;i++) x[i]=0;
while(nr!=0) { fc[(int)(nr%10)]++; nr=nr/10; nc++; }
k=0;
for(i=9;i>=0;i--)
if(fc[i]!=0)
for(j=1;j<=fc[i];j++) { k++; x[k]=i; }
for(i=1;i<=nc;i++) nrcd=nrcd*10+x[i];
return nrcd;
}// cifre(...)
public static void main(String[] args) throws IOException
{
int i,j;
int max,npmax,pmax;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("9-pluton.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("pluton.out")));
st.nextToken(); n=(int)st.nval;
for(i=1;i<=n;i++) {st.nextToken(); ni[i]=(int)st.nval;}
for(i=1;i<=n;i++) nid[i]=cifre(ni[i]);
154 CAPITOLUL 7. OJI 2006 CLASA A IX-A
np=0;
for(i=1;i<=n;i++)
{
if(nip[i]!=0) continue;
np++;
nip[i]=np;
for(j=i+1;j<=n;j++)
if(nip[j]==0)
if(nid[j]==nid[i]) nip[j]=np;
}
out.println(np);
for(i=1;i<=np;i++)
for(j=1;j<=n;j++) if(nip[j]==i) z[i]++;
max=0;
npmax=0;
pmax=0;
for(i=1;i<=np;i++) if(z[i]>max) {max=z[i];pmax=i;}
out.println(max);
for(i=1;i<=np;i++) if(z[i]==max) npmax++;
out.println(npmax);
for(i=1;i<=n;i++) if(nip[i]==pmax) out.print(ni[i]+" ");
out.println();
out.close();
}// main
}// class
Solut ie corecta si pentru Borland C++ 3.1
import java.io.*;
class Pluton2
{
static int n,np;
static int[] ni=new int[4001];
static int[] nid1=new int[4001];
static int[] nid2=new int[4001];
7.2. PLUTON 155
static int[] nip=new int[4001];
static int[] z=new int[4001];
static int[] fc=new int[10];
static int[] x=new int[11];
static void nrcd(int nr,int i0)
{
int i,j,k,nc;
int nrcd1, nrcd2; // nr cu cifre descrescatoare = |nrcd1|nrcd2|
for(i=0;i<=9;i++) fc[i]=0;
for(i=0;i<=10;i++) x[i]=0;
nc=0;
while(nr!=0) { fc[(int)(nr%10)]++; nr=nr/10; nc++; }
k=0;
for(i=0;i<=9;i++)
if(fc[i]!=0)
for(j=1;j<=fc[i];j++) { k++; x[k]=i; }
nrcd1=0;
for(i=nc;i>=6;i--) nrcd1=nrcd1*10+x[i];
nrcd2=0;
for(i=5;i>=1;i--) nrcd2=nrcd2*10+x[i];
nid1[i0]=nrcd1;
nid2[i0]=nrcd2;
}// cifre(...)
public static void main(String[] args) throws IOException
{
int i,j;
int max,npmax,pmax;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("pluton.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("pluton.out")));
st.nextToken(); n=(int)st.nval;
for(i=1;i<=n;i++) {st.nextToken(); ni[i]=(int)st.nval;}
156 CAPITOLUL 7. OJI 2006 CLASA A IX-A
for(i=1;i<=n;i++) nrcd(ni[i],i);
np=0;
for(i=1;i<=n;i++)
{
if(nip[i]!=0) continue;
np++;
nip[i]=np;
for(j=i+1;j<=n;j++)
if(nip[j]==0)
if((nid1[j]==nid1[i])&&(nid2[j]==nid2[i])) nip[j]=np;
}
out.println(np);
for(i=1;i<=np;i++)
for(j=1;j<=n;j++) if(nip[j]==i) z[i]++;
max=0;
npmax=0;
pmax=0;
for(i=1;i<=np;i++) if(z[i]>max) {max=z[i];pmax=i;}
out.println(max);
for(i=1;i<=np;i++) if(z[i]==max) npmax++;
out.println(npmax);
for(i=1;i<=n;i++) if(nip[i]==pmax) out.print(ni[i]+" ");
out.println();
out.close();
}// main
}// class
Capitolul 8
OJI 2007 clasa a IX-a
8.1 Cartele - OJI 2007
In sediul unei rme se intra doar cu ajutorul cartelelor magnetice. De cate ori
se schimba codurile de acces, cartelele trebuie formatate. Formatarea presupune
imprimarea unui model prin magnetizare. Dispozitivul n care se introduc cartelele,
numit cititor de cartele, verica acest model. Toate cartelele au aceleasi dimensiuni,
suprafat a patrata si grosimea neglijabila. Cele dou a fet e plane ale unei cartele se
mpart ecare n N N celule patrate, identice ca dimensiuni. Prin formatare
unele celule, marcate cu negru n exemplu, se magnetizeaza permit and radiat iei
infrarosii s a treac a dintr-o parte n cealalt a a cartelei.
In interiorul cititorului de
cartele se ilumineaz a uniform una dintre fet ele cartelei. De cealalt a parte fasciculele
de lumina care str abat cartela sunt analizate electronic. Pentru a permite accesul n
cladire modelul imprimat pe cartel a trebuie s a coincid a exact cu modelul sablonului
care memoreaz a codul de intrare. Prin fanta dispozitivului nu se pot introduce
mai multe cartele deodata. Cartela se poate introduce prin fant a cu oricare dintre
muchii spre deschizatura fantei si cu oricare dintre cele dou a fet e orientate catre
sablon. Dup a introducere cartela se dispune n plan paralel cu sablonul, lipit de
acesta, astfel ncat cele patru colt uri ale cartelei se suprapun exact cu colt urile
sablonului. Modelele imprimate pe cele dou a fet e ale unei cartele sunt identice.
Unei celule magnetizate i corespunde pe fat a opusa tot o celula magnetizata, iar
unei celule nemagnetizate i corespunde una nemagnetizat a. O celula magnetizata
este transparent a pentru radiat ia infrarosie indiferent de fat a care se ilumineaz a.
Un angajat al rmei are mai multe cartele. Pe unele dintre acestea a fost
imprimat noul cod de intrare, iar pe altele sunt coduri mai vechi. Pentru a aa
care sunt cartelele care-i permit accesul n sediul rmei angajatul este nevoit s a
le verice pe toate, introduc ndu-le pe r and, n toate modurile pe care le considera
necesare, n fanta cititorului de cartele.
157
158 CAPITOLUL 8. OJI 2007 CLASA A IX-A
Sablon Cartela 1 Cartela 2
Cerint a
Scriet i un program care determin a care dintre cartele permite accesul n sediul
rmei.
Date de intrare
Fisierul de intrare cartele.in cont ine pe prima linie dou a numere naturale
N si C desp art ite printr-un spat iu. N este dimensiunea tablourilor care reprezint a
modelul sablon si modelele cartelelelor. C reprezint a num arul de cartele. Urmeaza
C + 1 blocuri de cate N linii ecare. Primul bloc de N linii codic a sablonul.
Urm atoarele C blocuri de cate N linii codic a ecare cate o cartel a. Pe ecare linie
sunt cate N valori ntregi, desp art ite printr-un singur spat iu. Celulelor magnetizate
le corespunde valoarea 1, iar celorlalte, valoarea 0.
Date de iesire
In vederea asigurarii unei transmiteri cat mai exacte a informat iilor pe ret ea,
transmiterea se efectueaza caracter cu caracter, ecare caracter ind dat prin
codul s au ASCII, adica o grupa de 8 bit i (octet). Pentru ecare 8 bit i transmisi se
calculeaz a un bit de paritate care are valoarea 0 (daca codul ASCII al caracterului
cont ine un num ar par de cifre binare 1) sau 1 (n caz contrar).
Deoarece n problema noastra se transmit numai caractere ASCII standard,
cu codul ASCII din intervalul [32,127], codul lor ASCII are bitul 7 (primul bit
din st nga) egal cu 0. Pe aceast a pozit ie va pus bitul de paritate, economisind
astfel cate un bit pentru ecare caracter transmis. De exemplu, dac a mesajul care
trebuie trasmis cont ine caracterele Paritate, succesiunea de bit i transmis a va :
01010000 11100001 01110010 01101001 01110100 11100001 01110100 01100101
In acelasi timp variabila Eroare va cont ine ultima pozit ie a unui cod eronat
sau 0 dac a nu sunt erori la transmiterea mesajului.
Deoarece suntem asigurat i de faptul ca num arul de bit i 0/1 transmisi este
multiplu de 8, nu mai fac aceast a vericare si tratez ecare grupa de 8 bit i astfel:
- citesc primul caracter separat (este bitul de paritate)
- l transform n cifra 0/1
- citesc pe r and ceilalt i 7 bit i si formez codul ASCII corect num ar and n
acelasi timp bit ii egali cu 1
- dac a bitul de paritate este corect (adica am un num ar par de cifre 1) pun pe
pozit ia corespunzatoare din tablou caracterul al carui codl am - n caz contrar pun
pe pozit ia respectiv a valoarea #0 si ret in n variabila Eroare pozit ia caracterului
eronat
Dup a terminarea acestui proces nu am decat s a veric variabila Eroare:
- n cazul n care are valoarea 0 (transmisie far a eroare), asez DA n prima
linie a sierului de iesire, apoi parcurg vectorul caracter cu caracter si l scriu n
sierul de iesire, av and grij a ca n cazul nt alnirii caracterului #10 (cod de linie
nou a) s a trec la o nou a linie
- n cazul n care are o valoare 0 (transmisie cu erori) asez NU n prima
linie a sierului de iesire, apoi parcurg vectorul caracter cu caracter si, n cazul
nt alnirii valorii #0 (caracter eronat) asez indicele respectiv.
168 CAPITOLUL 8. OJI 2007 CLASA A IX-A
8.2.2 Rezolvare detaliata
8.2.3 Codul sursa *
Varianta 1: Versiunea este o prelucrare a variantei ociale; comentariile din
sursa au r amas nemodicate pentru ca sunt un exemplu bun!
import java.io.*;
class paritate
{
static final int MAX=60000;
static int[] a=new int[MAX]; // 0=eroare
public static void main(String[] args) throws IOException
{
int c;
int i,j,k;
int BitP, Cod, Bit, Nr1;
int Eroare; // ultima pozitie a unui cod eronat sau 0 daca nu sunt erori
//BufferedReader br0=new BufferedReader(new InputStreamReader(System.in));
BufferedReader br=new BufferedReader(new FileReader("paritate.in"));
PrintWriter out=new PrintWriter(new BufferedWriter(new FileWriter("paritate.out")));
i=-1;
Eroare=0;
c=0;
String s=br.readLine();
//System.out.println("s = "+s);
k=0;
while(k<s.length()-1)
{
c=s.charAt(k);
//System.out.println(k+" : "+c);
//br0.readLine();
i++; // pozitie caracter
BitP=c-0; // bitul de paritate
Cod=0; // aici formez codul
Nr1=0; // cati de 1
for(j=1;j<=7;j++) // citesc ceilalti 7 biti
{
c=s.charAt(++k); // citesc bit
//System.out.println(k+" : "+c);
8.2. PARITATE - OJI 2007 169
//br0.readLine();
Bit=c-0;
if(Bit==1) Nr1++; // daca e 1 il numar
Cod=Cod*2+Bit; // formez codul
}
if((Nr1+BitP)%2==0) // daca cod corect
a[i]=Cod; // pun caracterul in vector
else // altfel
{
a[i]=1; // pun 1
Eroare=i; // si retin pozitia
}
++k;
}// while
if(Eroare==0) // daca nu sunt erori
{
out.println("DA"); // scrie DA si
for(j=0;j<=i;j++) // afiseaza cele i+1 caractere
if(a[j]==10) // avand grija la caracterul cu codul 10
out.println();
else // altfel
out.print((char)a[j]); // scrie caracterul
}
else // eroare!!!
{
out.println("NU"); // scrie NU si
for(j=0;j<Eroare;j++)
if(a[j]==1) // cauta erorile - cod 01
out.print(j+" "); // si afiseaza pozitia lor
out.println(Eroare); // afiseaza pozitia ultimei erori
}
out.close();
}// main
}// class
170 CAPITOLUL 8. OJI 2007 CLASA A IX-A
Capitolul 9
ONI 2000 clasa a IX-a
9.1 Algoritm
prof. Roxana T amplaru, Liceul Stefan Odobleja, Craiova
Georgel scrie un algoritm care cont ine structuri de atribuire, alterna-
tive, de select ie, repetitive si compuse. Dup a scrierea algoritmului vrea s a-l testeze
pentru toate cazurile posibile. Pentru aceasta trebuie s a cunoasc a num arul minim
de date de test necesare.
Pentru descrirea structurilor se utilizeaza urmatoarele cuvinte cheie:
- pentru atribuire ATRIB
- pentru alternativ a DACA
ATUNCI
ALTFEL unde ALTFEL poate lipsi
- pentru select ie ALEGE
CAZ
CAZ IMPLICIT unde CAZ IMPLICIT poate lipsi
- pentru repetitive 1) CAT TIMP
2) REPETA
PANA CAND
3) PENTRU
- pentru compus a INCEPUT
SFARSIT
171
172 CAPITOLUL 9. ONI 2000 CLASA A IX-A
Nu se face diferent a ntre literele mari si literele mici. Un algoritm ncepe cu
cuvantul cheie INCEPUT, se termina cu SFARSIT si nu cont ine structuri vide. De
asemenea o structur a compus a ncepe cu cuvantul cheie INCEPUT si se termina
cu SFARSIT.
Cerint a
Sa se calculeze num arul minim de date de test necesare pentru vericarea
algoritmului.
Date de intrare:
Din sierul text ALGOR.IN se citeste algoritmul.
Fisierul cont ine pe ecare linie cate un singur cuvant cheie.
Nu exista linii vide.
Algoritmul respecta principiile programarii structurate si este scris corect.
Date de iesire:
In mod normal toate camerele ar trebui s a e deschise, dar o parte dintre ele
sunt nchise si pot deschise doar cu ajutorul unor cartele speciale. Astfel, ecare
camera si ecare cartel a are asociat un num ar ntre 0 si 20; o camera cu num arul
asociat 0 este deschis a de la nceput, n timp ce una cu num arul asociat diferit de
0 este init ial nchis a, poate deschis a din interior sau din exterior dintr-o camera
vecin a cu o cartel a cu num arul corespunzator si va r amane deschis a ulterior.
Cartelele cu num arul asociat 0 nu au nici o ntrebuint are practica. Un num ar
poate asociat mai multor cartele, respectiv camere. Dintr-o camera se poate
trece n alta numai dac a ele sunt vecine si ambele sunt deschise. Doua camere se
considera vecine dac a au un perete (deci o latura) n comun.
Intr-o cladire cu h etaje sunt det inut i, la parter, cat iva prizonieri de
catre T teroristi. Fiecare etaj al cladirii are mn camere identice. Fiecare camera
are un cod numeric (nu neaparat unic) exprimat printr-un num ar din intervalul
0 255.
O trupa de komando, format a din K specialisti n luptele antitero, trebuie s a
elibereze prizonierii. Trupa de komando este parasutata pe cladire si ncearc a s a
ajunga la parter. Se cunoaste locul (x, y) unde ecare membru al trupei a aterizat
pe acoperis.
Greutatea ecarui membru al trupei este exprimat a n unitat i din intervalul
1 255. Un membru al trupei poate trece n jos printr-o camera a cladirii doar
dac a greutatea lui trece prin camera respectiv a, conform urmatoarei denit ii.
Denit ie: Spunem ca a trece prin b (a >> b) dac a, n reprezentare binara,
num arul de cifre 1 a lui a este mai mic sau egal cu num arul de cifre 1 a lui b si
cifrele 1 ale lui a sunt comune cu unele cifre 1 ale lui b.
Exemplu: 44 trece prin 174 (44 >> 174) deoarece
44 = 00101100
174 = 10101110
Pentru detectarea unei camere prin care s a poat a trece, un membru al trupei
196 CAPITOLUL 9. ONI 2000 CLASA A IX-A
de komando se poate, eventual, deplasa cu un pas n cele 8 direct ii al aturate
pozit iei curente n care a ajuns prin aterizare sau trecerea n jos. Prin pas-ul
respectiv se ajunge la una din cele 8 camere vecine. Prizonierii pot eliberat i doar
dac a la parter ajung minim T membri ai trupei de komando.
Cerint a:
Sa se determine dac a prizonierii pot eliberat i sau nu, precum si num arul
de membri ai trupei de komando care pot s a ajunga la parter.
Date de intrare
Fisierul text KOMMANDO.IN are structura urmatoare:
pe prima linie valorile m, n, h, K, T desp art ite prin cate un spat iu, cu
semnicat iile descrise mai sus;
urmatoarele h linii reprezint a codurile celor m n camere ale unui etaj,
desp art ite prin cate un spat iu;
ultimele K linii ale sierului cont in greutatea si coordonatele x si y a pozit iei
de aterizare pe acoperis ale celor K membri ai trupei de komando, pentru ecare
pe cate o linie, desp art ite prin cate un spat iu:
m n h K T
c
111
c
112
... c
11n
c
121
c
122
... c
12n
... c
1m1
... c
1mn
...
c
h11
c
h12
... c
h1n
c
h21
c
h22
... c
h2n
... c
hm1
... c
hmn
G
1
x
1
y
1
...
G
K
x
K
y
K
Datele de iesire:
Fisierul text KOMMANDO.OUT cu structura:
DA sau NU - pe prima linie;
num arul de membri ai trupei de komando ajunsi la parter - pe linia a doua.
Restrict ii si precizari
2 m, n, h 35 1 x
i
m 1 y
i
n
1 T, K, G
i
255
0 c
ijk
255
Toate valorile sunt ntregi.
Exemplu:
9.6. KOMMANDO 197
KOMMANDO.IN KOMMANDO.OUT
5 5 5 3 2 DA
0 0 0 0 0 0 0 33 0 0 0 0 2 0 0 0 0 0 3 0 0 0 0 0 0 2
0 0 0 0 0 0 1 0 0 0 0 44 2 0 0 0 0 0 3 0 0 0 0 0 0
0 0 0 0 0 11 0 0 0 0 0 0 2 22 0 0 0 0 0 3 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 66 2 0 0 0 0 0 7 0 15 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 2 2
2 3 3
3 4 4
Timp maxim de execut ie pe test: 5 secunde
9.6.1 Indicat ii de rezolvare - descriere solut ie *
In sierul de intrare etajele sunt de sus n jos (primul etaj este l anga acoperis)!
Pentru ecare soldat se face o parcurgeren ad ancime (folosind recursivitatea)
sau o parcurgere n l at ime (eventual folosind o structur a de tip coad a) pentru un
algoritm de tip ll (umplere).
9.6.2 Rezolvare detaliata
9.6.3 Codul sursa *
import java.io.*; // 35*35*35=42875
class Kommando1 // parcurgere in adancime
{
static int m,n,h,K,T;
static int[][][] codCamera; // cod camera
static int[] xk; // x acoperis soldat k
static int[] yk; // y acoperis soldat k
static int[] G; // greutatea
static int ns=0; // nr soldati ajunsi la parter
static boolean aajunslaparter;
static PrintWriter out;
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
198 CAPITOLUL 9. ONI 2000 CLASA A IX-A
citire();
rezolvare();
afisare();
}
static void citire() throws IOException
{
int x,y,etaj,k;
st=new StreamTokenizer(
new BufferedReader(new FileReader("0.in")));
st.nextToken(); m=(int)st.nval;
st.nextToken(); n=(int)st.nval;
st.nextToken(); h=(int)st.nval;
st.nextToken(); K=(int)st.nval;
st.nextToken(); T=(int)st.nval;
codCamera=new int[h+1][m+1][n+1];
xk=new int[K+1];
yk=new int[K+1];
G=new int[K+1];
for(etaj=1;etaj<=h;etaj++)
for(x=1;x<=m;x++)
for(y=1;y<=n;y++)
{
st.nextToken();
codCamera[etaj][x][y]=(int)st.nval;
}
for(k=1;k<=K;k++)
{
st.nextToken(); G[k]=(int)st.nval;
st.nextToken(); xk[k]=(int)st.nval;
st.nextToken(); yk[k]=(int)st.nval;
}
}
static void rezolvare() throws IOException
{
int soldat;
for(soldat=1;soldat<=K;soldat++)
{
System.out.println(soldat);
aajunslaparter=false;
9.6. KOMMANDO 199
coboara(soldat,1,xk[soldat],yk[soldat]);
if(aajunslaparter) ns++;
}
}
static void coboara(int soldat, int etaj, int x, int y)
{
System.out.println(soldat+" "+etaj+" "+x+" "+y);
if((x<1)||(x>m)||(y<1)||(y>n)) return;
if(aajunslaparter) return;
if(etaj==h) {aajunslaparter=true; return;}
int i,j;
for(i=-1;i<=1;i++)
for(j=-1;j<=1;j++)
if((x+i>=1)&&(x+i<=m)&&(y+j>=1)&&(y+j<=n))
if(trece(G[soldat],codCamera[etaj][x+i][y+j]))
coboara(soldat, etaj+1, x+i, y+j);
}
static boolean trece(int a, int b) // a trece prin b ?
{
int k;
for(k=0;k<=7;k++)
if(((1<<k)&a)!=0) // pozitia k in a este 1
if(((1<<k)&b)==0) // pozitia k in b este 0
return false;
return true;
}
static void afisare() throws IOException
{
out=new PrintWriter(
new BufferedWriter(new FileWriter("kommando.out")));
if(ns>=T) out.println("DA"); else out.println("NU");
out.println(ns);
out.close();
}
}
import java.io.*; // optimizare prin inregistrarea traseului
class Kommando2 // totusi, test 10 ==> 13.5 sec ???
{
static int m,n,h,K,T;
static int[][][] codCamera; // cod camera
200 CAPITOLUL 9. ONI 2000 CLASA A IX-A
static int[] xk; // x acoperis soldat k
static int[] yk; // y acoperis soldat k
static int[] G; // greutatea
static int ns=0; // nr soldati ajunsi la parter
static boolean aajunslaparter;
static boolean[][][] traseu; // traseul soldatului curent
static PrintWriter out;
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
long t1,t2;
t1=System.currentTimeMillis();
citire();
rezolvare();
afisare();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1)+" ms");
}
static void citire() throws IOException
{
int x,y,etaj,k;
st=new StreamTokenizer(
new BufferedReader(new FileReader("10.in")));
st.nextToken(); m=(int)st.nval;
st.nextToken(); n=(int)st.nval;
st.nextToken(); h=(int)st.nval;
st.nextToken(); K=(int)st.nval;
st.nextToken(); T=(int)st.nval;
codCamera=new int[h+1][m+1][n+1];
traseu=new boolean[h+1][m+1][n+1];
xk=new int[K+1];
yk=new int[K+1];
G=new int[K+1];
for(etaj=1;etaj<=h;etaj++)
for(x=1;x<=m;x++)
for(y=1;y<=n;y++)
9.6. KOMMANDO 201
{
st.nextToken();
codCamera[etaj][x][y]=(int)st.nval;
}
for(k=1;k<=K;k++)
{
st.nextToken(); G[k]=(int)st.nval;
st.nextToken(); xk[k]=(int)st.nval;
st.nextToken(); yk[k]=(int)st.nval;
}
}
static void rezolvare() throws IOException
{
int soldat;
for(soldat=1;soldat<=K;soldat++)
{
curatTraseu();
aajunslaparter=false;
coboara(soldat,1,xk[soldat],yk[soldat]);
if(aajunslaparter) ns++;
}
}
static void curatTraseu()
{
int etaj, x, y;
for(etaj=1;etaj<=h;etaj++)
for(x=1;x<=m;x++)
for(y=1;y<=n;y++)
traseu[etaj][x][y]=false;
}
static void coboara(int soldat, int etaj, int x, int y)
{
if((x<1)||(x>m)||(y<1)||(y>n)) return;
if(aajunslaparter) return;
if(etaj==h) {aajunslaparter=true; return;}
if(traseu[etaj][x][y]) return; // a mai trecut pe aici
traseu[etaj][x][y]=true;
int i,j;
for(i=-1;i<=1;i++)
202 CAPITOLUL 9. ONI 2000 CLASA A IX-A
for(j=-1;j<=1;j++)
if((x+i>=1)&&(x+i<=m)&&(y+j>=1)&&(y+j<=n))
if(trece(G[soldat],codCamera[etaj][x+i][y+j]))
coboara(soldat, etaj+1, x+i, y+j);
}
static boolean trece(int a, int b) // a trece prin b ?
{
int k;
for(k=0;k<=7;k++)
if(((1<<k)&a)!=0) // pozitia k in a este 1
if(((1<<k)&b)==0) // pozitia k in b este 0
return false;
return true;
}
static void afisare() throws IOException
{
out=new PrintWriter(
new BufferedWriter(new FileWriter("kommando.out")));
if(ns>=T) out.println("DA"); else out.println("NU");
out.println(ns);
out.close();
}
}
import java.io.*; // parcurgere in latime
class Kommando3 // totusi, test 10 ==> 10.5 sec ???
{
static int m,n,h,K,T;
static int[][][] codCamera; // cod camera
static int[] xk; // x acoperis soldat k
static int[] yk; // y acoperis soldat k
static int[] G; // greutatea
static int ns=0; // nr soldati ajunsi la parter
static boolean aajunslaparter;
static boolean[][][] ok; // soldat poate trece prin camera
static PrintWriter out;
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
long t1,t2;
9.6. KOMMANDO 203
t1=System.currentTimeMillis();
citire();
rezolvare();
afisare();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1)+" ms");
}
static void citire() throws IOException
{
int x,y,etaj,k;
st=new StreamTokenizer(
new BufferedReader(new FileReader("0.in")));
st.nextToken(); m=(int)st.nval;
st.nextToken(); n=(int)st.nval;
st.nextToken(); h=(int)st.nval;
st.nextToken(); K=(int)st.nval;
st.nextToken(); T=(int)st.nval;
codCamera=new int[h+1][m+1][n+1];
ok=new boolean[h+1][m+1][n+1];
xk=new int[K+1];
yk=new int[K+1];
G=new int[K+1];
for(etaj=1;etaj<=h;etaj++)
for(x=1;x<=m;x++)
for(y=1;y<=n;y++)
{
st.nextToken();
codCamera[etaj][x][y]=(int)st.nval;
}
for(k=1;k<=K;k++)
{
st.nextToken(); G[k]=(int)st.nval;
st.nextToken(); xk[k]=(int)st.nval;
st.nextToken(); yk[k]=(int)st.nval;
}
}
204 CAPITOLUL 9. ONI 2000 CLASA A IX-A
static void rezolvare() throws IOException
{
int soldat,etaj,x,y;
for(soldat=1;soldat<=K;soldat++)
{
System.out.println(soldat);
curatTraseu();
aajunslaparter=false;
etaj=1;
x=xk[soldat];
y=yk[soldat];
coboara(soldat,etaj,x,y); // coboara din (x,y) si vecini
for(etaj=2;etaj<=h;etaj++)
for(x=1;x<=m;x++)
for(y=1;y<=n;y++)
if(ok[etaj][x][y]) coboara(soldat,etaj,x,y);
if(aajunslaparter) ns++;
}
}
static void coboara(int soldat, int etaj, int x, int y)
{
if(etaj==h) {aajunslaparter=true; return;}
int i,j;
for(i=-1;i<=1;i++)
for(j=-1;j<=1;j++)
if((x+i>=1)&&(x+i<=m)&&(y+j>=1)&&(y+j<=n))
if(trece(G[soldat],codCamera[etaj][x+i][y+j]))
ok[etaj+1][x+i][y+j]=true;
}
static boolean trece(int a, int b) // a trece prin b ?
{
int k;
for(k=0;k<=7;k++)
if(((1<<k)&a)!=0) // pozitia k in a este 1
if(((1<<k)&b)==0) // pozitia k in b este 0
return false;
return true;
}
static void curatTraseu()
{
int etaj, x, y;
9.6. KOMMANDO 205
for(etaj=1;etaj<=h;etaj++)
for(x=1;x<=m;x++)
for(y=1;y<=n;y++)
ok[etaj][x][y]=false;
}
static void afisare() throws IOException
{
out=new PrintWriter(
new BufferedWriter(new FileWriter("kommando.out")));
if(ns>=T) out.println("DA"); else out.println("NU");
out.println(ns);
out.close();
}
}
import java.io.*; // parcurgere in latime
class Kommando4 // test 10 ==> 4.9 sec
{ // se poate si mai bine folosind traseu="coada" !!!
static int m,n,h,K,T;
static int[][][] codCamera; // cod camera
static int[] xk; // x acoperis soldat k
static int[] yk; // y acoperis soldat k
static int[] G; // greutatea
static int ns=0; // nr soldati ajunsi la parter
static boolean aajunslaparter;
static boolean[][][] ok; // soldat poate trece prin camera
static boolean[][][] traseu;// soldat a mai fost aici
static PrintWriter out;
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
long t1,t2;
t1=System.currentTimeMillis();
citire();
rezolvare();
afisare();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1)+" ms");
}
206 CAPITOLUL 9. ONI 2000 CLASA A IX-A
static void citire() throws IOException
{
int x,y,etaj,k;
st=new StreamTokenizer(
new BufferedReader(new FileReader("10.in")));
st.nextToken(); m=(int)st.nval;
st.nextToken(); n=(int)st.nval;
st.nextToken(); h=(int)st.nval;
st.nextToken(); K=(int)st.nval;
st.nextToken(); T=(int)st.nval;
codCamera=new int[h+1][m+1][n+1];
ok=new boolean[h+1][m+1][n+1];
traseu=new boolean[h+1][m+1][n+1];
xk=new int[K+1];
yk=new int[K+1];
G=new int[K+1];
for(etaj=1;etaj<=h;etaj++)
for(x=1;x<=m;x++)
for(y=1;y<=n;y++)
{
st.nextToken();
codCamera[etaj][x][y]=(int)st.nval;
}
for(k=1;k<=K;k++)
{
st.nextToken(); G[k]=(int)st.nval;
st.nextToken(); xk[k]=(int)st.nval;
st.nextToken(); yk[k]=(int)st.nval;
}
}
static void rezolvare() throws IOException
{
int soldat,etaj,x,y;
for(soldat=1;soldat<=K;soldat++)
{
curatTraseu();
aajunslaparter=false;
etaj=0;
9.6. KOMMANDO 207
x=xk[soldat];
y=yk[soldat];
coboara(soldat,etaj,x,y);
for(etaj=1;etaj<=h;etaj++)
for(x=1;x<=m;x++)
for(y=1;y<=n;y++)
if(ok[etaj][x][y]) coboara(soldat,etaj,x,y);
if(aajunslaparter) ns++;
}
}
static void coboara(int soldat, int etaj, int x, int y)
{
if(etaj==h) {aajunslaparter=true; return;}
int i,j;
for(i=-1;i<=1;i++)
for(j=-1;j<=1;j++)
if((x+i>=1)&&(x+i<=m)&&(y+j>=1)&&(y+j<=n))
if(!traseu[etaj+1][x+i][y+j])
{
traseu[etaj+1][x+i][y+j]=true;
if(trece(G[soldat],codCamera[etaj+1][x+i][y+j]))
ok[etaj+1][x+i][y+j]=true;
}
}
static boolean trece(int a, int b) // a trece prin b ?
{
int k;
for(k=0;k<=7;k++)
if(((1<<k)&a)!=0) // pozitia k in a este 1
if(((1<<k)&b)==0) // pozitia k in b este 0
return false;
return true;
}
static void curatTraseu()
{
int etaj, x, y;
for(etaj=0;etaj<=h;etaj++)
for(x=1;x<=m;x++)
for(y=1;y<=n;y++)
{
ok[etaj][x][y]=false;
208 CAPITOLUL 9. ONI 2000 CLASA A IX-A
traseu[etaj][x][y]=false;
}
}
static void afisare() throws IOException
{
out=new PrintWriter(
new BufferedWriter(new FileWriter("kommando.out")));
if(ns>=T) out.println("DA"); else out.println("NU");
out.println(ns);
out.close();
}
}
Capitolul 10
ONI 2001 clasa a IX-a
10.1 Ferma
prof. Maria Nit a si prof. Adrian Nit a, Oradea
Un fermier are un teren care are forma unui tablou dreptunghiular lung
de M unitat i si lat de N unitat i. Pe teren sunt plantat i din loc n loc copaci,
pe care fermierul nu doreste s a-i taie. Dorind s a-si supravegheze cultura, fermierul
realizeaza un mic robot de forma patrata av and latura de 3 unitat i pe care l poate
teleghida prin ferm a, parcurgand unitate cu unitate o anumita suprafat a.
Robotul se poate misca pe verticala si pe orizontala dar, nu poate trece peste
copaci, nu i poate distruge, nu se poate roti si are nevoie pentru miscare de o
suprafat a corespunzatoare dimensiunii lui.
Cerint a
Ajutat i-l pe fermier s a determine suprafat a maxima pe care o poate urmari,
folosind acest sistem.
209
210 CAPITOLUL 10. ONI 2001 CLASA A IX-A
Date de intrare
Fisier de intrare: FERMA.IN
Linia 1: N M - dou a numere naturale nenule, separate pritr-un spat iu,
reprezent and num arul de linii (N), respectiv num arul de coloane (M);
Liniile 2..N+1: C
1
C
2
...C
M
- aceste N linii codic a ferma; ecare linie
cont ine cate M caractere (far a s a e separate prin spat ii) av and semnicat ia:
. - teren liber;
+ - locul n care este plantat un copac;
R - centrul robotului.
Date de iesire
Fisier de iesire: FERMA.OUT
Liniile 1..N: C
1
C
2
...C
M
- aceste N linii codic a modul n care fermierul
poate s a-si utilizeze robotul pe terenul s au; ecare linie cont ine cate M caractere
(far a s a e separate prin spat ii) av and semnicat ia:
. - teren neacoperit de robot;
* - teren ce poate vericat de robot;
+ - loc n care a r amas copacul.
Restrict ii
1 N, M 50
Exemplu
FERMA.IN
12 11
. . . . . . . . . . .
. . . + . . . . . + .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . + . . . . . . .
. + . . . R . . . . .
. . . . . . . . . + .
. . + . . . . . . . +
. . . . . . + . . . .
. . . . . . . . . . .
. . . . . . + . . . .
FERMA.OUT
10.1. FERMA 211
. . . . * * * * * . .
. . . + * * * * * + .
. . * * * * * * * * *
. . * * * * * * * * *
. + * * * * * * * * *
. . . + * * * * * * *
. + . * * * * * * * *
. . . * * * * * * + .
. . + * * * * * * . +
* * * * * * + . . . .
* * * * * * . . . . .
* * * * * * + . . . .
Timp maxim de executare/test: 3 secunde
10.1.1 Indicat ii de rezolvare - descriere solut ie *
Se foloseste un algoritm de tip ll (umplere) folosind recursivitatea, plec and
din pozit ia init iala a robotului si t inand cont de restrict iile problemei.
10.1.2 Rezolvare detaliata *
import java.io.*;
class Ferma1
{
static int n,m;
static int[][] a=new int[51][51]; // ferma
static PrintWriter out;
public static void main(String[] args) throws IOException
{
int i,j,k;
int ic,sc;
out=new PrintWriter(new BufferedWriter(new FileWriter("ferma.out")));
BufferedReader br=new BufferedReader(new FileReader("ferma.in"));
StreamTokenizer st=new StreamTokenizer(br);
st.nextToken(); n=(int)st.nval;
st.nextToken(); m=(int)st.nval;
System.out.println("n="+n+" m="+m);
br.readLine();// citeste LF adica 0A adica 10
for(i=1;i<=n;i++)
212 CAPITOLUL 10. ONI 2001 CLASA A IX-A
{
for(j=1;j<=m;j++)
{
a[i][j]=br.read();
System.out.print(a[i][j]+" ");
}
br.readLine(); // citeste CR LF adica 0D 0A adica 13 10
System.out.println();
}
System.out.println();
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++) System.out.print((char) a[i][j]+" ");
System.out.println();
}
out.close();
}
}
10.1.3 Codul sursa *
import java.io.*;
class Ferma2
{
static int n,m;
static int[][] a=new int[51][51]; // ferma codificata
static PrintWriter out;
static final int liber=(int).,copac=(int)+,robot=(int)*;
public static void main(String[] args) throws IOException
{
int i,j,ir=0,jr=0;
int ic,sc;
out=new PrintWriter(new BufferedWriter(new FileWriter("ferma.out")));
BufferedReader br=new BufferedReader(new FileReader("ferma.in"));
StreamTokenizer st=new StreamTokenizer(br);
st.nextToken(); n=(int)st.nval;
st.nextToken(); m=(int)st.nval;
br.readLine();// citeste LF = 0x0A =10
10.1. FERMA 213
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++) a[i][j]=br.read();
br.readLine(); // citeste CR LF adica 0D 0A adica 13 10
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
if(a[i][j]==(int)R) {ir=i; jr=j; break;};
for(i=-1;i<=1;i++)
for(j=-1;j<=1;j++) a[ir+i][jr+j]=robot;
deplasareDin(ir,jr);
afism();
out.close();
}
static void deplasareDin(int ir, int jr)
{
if(ir-2>=1) // sus
if((a[ir-2][jr-1]!=copac)&&(a[ir-2][jr]!=copac)&&(a[ir-2][jr+1]!=copac))
if((a[ir-2][jr-1]==liber)||(a[ir-2][jr]==liber)||(a[ir-2][jr+1]==liber))
{
a[ir-2][jr-1]=a[ir-2][jr]=a[ir-2][jr+1]=robot;
deplasareDin(ir-1,jr);
}
if(ir+2<=n) // jos
if((a[ir+2][jr-1]!=copac)&&(a[ir+2][jr]!=copac)&&(a[ir+2][jr+1]!=copac))
if((a[ir+2][jr-1]==liber)||(a[ir+2][jr]==liber)||(a[ir+2][jr+1]==liber))
{
a[ir+2][jr-1]=a[ir+2][jr]=a[ir+2][jr+1]=robot;
deplasareDin(ir+1,jr);
}
if(jr-2>=1) // stanga
if((a[ir-1][jr-2]!=copac)&&(a[ir][jr-2]!=copac)&&(a[ir+1][jr-2]!=copac))
if((a[ir-1][jr-2]==liber)||(a[ir][jr-2]==liber)||(a[ir+1][jr-2]==liber))
{
a[ir-1][jr-2]=a[ir][jr-2]=a[ir+1][jr-2]=robot;
deplasareDin(ir,jr-1);
}
if(jr+2<=m) // dreapta
214 CAPITOLUL 10. ONI 2001 CLASA A IX-A
if((a[ir-1][jr+2]!=copac)&&(a[ir][jr+2]!=copac)&&(a[ir+1][jr+2]!=copac))
if((a[ir-1][jr+2]==liber)||(a[ir][jr+2]==liber)||(a[ir+1][jr+2]==liber))
{
a[ir-1][jr+2]=a[ir][jr+2]=a[ir+1][jr+2]=robot;
deplasareDin(ir,jr+1);
}
}
static void afism()
{
int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++) out.print((char) a[i][j]);
out.println();
}
out.println();
}
}
10.2 Fract ii
prof. Ovidiu Domsa, Alba Iulia
O proprietate interesant a a fract iilor ireductibile este ca orice fract ie se
poate obt ine dupa urmatoarele reguli:
pe primul nivel se aa fract ia 1/1;
pe al doilea nivel, n stanga fract iei 1/1 de pe primul nivel, plas am fract ia
1/2 iar n dreapta ei fract ia 2/1;
nivelul 1: 1/1
nivelul 2: 1/2 2/1
pe ecare nivel k se plaseaza sub ecare fract ie i/j de pe nivelul de deasupra,
fract ia i/(i +j) n stanga, iar fract ia (i +j)/j n dreapta.
nivelul 1: 1/1
nivelul 2: 1/2 2/1
nivelul 3: 1/3 3/2 2/3 3/1
Cerint a
Dandu-se o fract ie oarecare prin num ar atorul si numitorul s au, determinat i
num arul nivelului pe care se aa fract ia sau o fract ie echivalent a (av and aceeasi
valoare) cu aceasta.
Date de intrare
Fisier de intrare: FRACTII.IN
10.2. FRACT II 215
Linia 1: N M - dou a numere naturale nenule, separate printr-un spat iu,
reprezent and num ar atorul si numitorul unei fract ii.
Date de iesire
Fisier de iesire: FRACTII.OUT
Linia 1: niv - num ar natural nenul, reprezent and num arul nivelului care
corespunde fract iei.
Restrict ii
1 < N, M 2.000.000.000
Exemple
FRACTII.IN FRACTII.OUT FRACTII.IN FRACTII.OUT
13 8 6 12 8 3
Timp maxim de execut ie: 1 secunda/test
10.2.1 Indicat ii de rezolvare - descriere solut ie *
Se aduce fract ia la o fract ie echivalent a ireductibila. Nu se coboara n arbore
ci se urca din pozit ia fract iei echivalente pana la fract ia 1/1 din v arful arborelui
de fract ii.
10.2.2 Rezolvare detaliata
10.2.3 Codul sursa *
import java.io.*;
class Fractii
{
public static void main(String[] args) throws IOException
{
int n,m,k,d;
StreamTokenizer st=new StreamTokenizer(new BufferedReader(
new FileReader("fractii.in")));
PrintWriter out=new PrintWriter(new BufferedWriter(
new FileWriter("fractii.out")));
st.nextToken();n=(int)st.nval;
st.nextToken();m=(int)st.nval;
k=0;
d=cmmdc(n,m);
n=n/d;
216 CAPITOLUL 10. ONI 2001 CLASA A IX-A
m=m/d;
while((n!=1)||(m!=1))
{
k++;
if(n>m) n=n-m; else m=m-n;
}
k++;
out.println(k);
out.close();
}
static int cmmdc(int a, int b)
{
int d,i,c,r;
if(a>b) {d=a; i=b;} else {d=b; i=a;}
while(i!=0) {c=d/i; r=d%i; d=i; i=r;}
return d;
}
}
10.3 Tablou
prof. Rodica Pintea, Bucuresti
Generat i un tablou bidimensional cu propriet at ile:
cont ine N linii si N coloane;
elementele sale sunt numere naturale nenule;
suma elementelor este egal a cu num arul natural nenul S;
pe nici o linie si pe nici o coloana nu exista dou a elemente identice;
diferent a dintre cel mai mare si cel mai mic element ale tabloului este
minima.
Date de intrare
Fisier de intrare: TABLOU.IN
Linia 1: N S - dou a numere naturale nenule, separate printr-un spat iu,
reprezent and num arul de linii si de coloane ale tabloului, respectiv valoarea sumei
tuturor elementelor din tablou;
Date de iesire
Fisier de iesire: TABLOU.OUT
Linia 1..N: nr
11
nr
12
... nr
1N
nr
21
nr
22
... nr
2N
.........................
nr
N1
nr
N2
... nr
NN
10.3. TABLOU 217
pe aceste N linii se vor scrie elementele tabloului, cate o linie din tablou pe
o linie din sier; elementele se vor separa prin cate un spat iu.
Restrict ii si precizari
1 < N 100
0 < S 2
31
Daca problema nu are solut ie, n sierul de iesire se va scrie cifra 0.
Daca problema are mai multe solut ii, n sier se va scrie una singur a.
Exemplu
TABLOU.IN TABLOU.OUT
3 51 4 6 7
7 4 5
5 7 6
Timp maxim de execut ie: 1 sec/test
10.3.1 Indicat ii de rezolvare - descriere solut ie *
Se determin a cel mai mare num ar natural x cu proprietatea n(x + x + 1 +
... + x + n 1) < s si se plaseaza cele n numere x, x + 1, ..., x + n 1 pe linii,
permutandu-le circular de la o linie la alta. Astfel, pe ecare linie si ecare coloana
vor numere diferite. Se maresc cu cate o unitate, dac a este cazul, cele mai mari
numere din matrice pana cand suma tuturor elementelor matricei este egal a cu s.
10.3.2 Rezolvare detaliata *
import java.io.*; // max --> [i][j] cu (i+j)%n==n-1
class Tablou1 // min --> [i][j] cu (i+j)%n==0
{ // (i+j)%n=k ==> j=?=(n-i+k-1)%n
static int n,s,x,sp,p; // p=puncte ramase < n*n
static int[][] a;
public static void main(String[] args) throws IOException
{
int i,j,k;
StreamTokenizer st=new StreamTokenizer(new BufferedReader(
new FileReader("tablou.in")));
PrintWriter out=new PrintWriter(new BufferedWriter(
new FileWriter("tablou.out")));
st.nextToken();n=(int)st.nval;
st.nextToken();s=(int)st.nval;
a=new int[n][n];
218 CAPITOLUL 10. ONI 2001 CLASA A IX-A
x=(2*s-n*n*n+n*n)/(2*n*n);
System.out.println("x="+x);
sp=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
a[i][j]=x+(i+j)%n;
sp+=a[i][j];
}
p=s-sp;
System.out.println("sp="+sp+" s="+s+" p="+p);
System.out.println(); afism();
k=x+n-1;
while(p>0)
{
i=0;
while((p>0)&&(i<n)) // k=valoarea pe care o maresc cu 1
{
j=(n-i+k-1)%n;
System.out.println("k="+k+" i="+i+" j="+j+" p="+p);
a[i][j]++;
i++; p--;
}
System.out.println(); afism();
k--;
}
System.out.println(); afism();
out.close();
}
static void afism()
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++) System.out.print(a[i][j]+" ");
System.out.println();
}
}
}
10.3. TABLOU 219
10.3.3 Codul sursa *
import java.io.*; // max --> [i][j] cu (i+j)%n==n-1
class Tablou2 // min --> [i][j] cu (i+j)%n==0
{ // (i+j)%n=k ==> j=?=(n-i+k-1)%n
static int n,s,x,sp,p; // p=puncte ramase < n*n
static int[][] a;
public static void main(String[] args) throws IOException
{
int i,j,k;
StreamTokenizer st=new StreamTokenizer(new BufferedReader(
new FileReader("tablou.in")));
PrintWriter out=new PrintWriter(new BufferedWriter(
new FileWriter("tablou.out")));
st.nextToken();n=(int)st.nval;
st.nextToken();s=(int)st.nval;
a=new int[n][n];
x=(2*s-n*n*n+n*n)/(2*n*n);
sp=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
a[i][j]=x+(i+j)%n;
sp+=a[i][j];
}
p=s-sp;
k=x+n-1;
while(p>0)
{
i=0;
while((p>0)&&(i<n)) // k=valoarea pe care o maresc cu 1
{
j=(n-i+k-1)%n;
a[i][j]++;
i++; p--;
}
k--;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++) out.print(a[i][j]+" ");
220 CAPITOLUL 10. ONI 2001 CLASA A IX-A
out.println();
}
out.close();
}
}
10.4 Competit ie dicila
Angel Proorocu, Bucuresti
La o competit ie au participat N concurent i. Fiecare dintre ei a primit
un num ar de concurs astfel ncat s a nu existe concurent i cu acelasi num ar.
Numerele de concurs apart in mult imii {1, 2, ..., N}.
Din pacate, clasamentul nal a fost pierdut, iar comisiasi poate aduce aminte
doar cateva relat ii ntre unii participant i (de genul participantul cu num arul 3 a
iesit naintea celui cu num arul 5).
Cerint a
Seful comisiei are nevoie de un clasament nal si v a cere s a-l ajutat i deter-
minand primul clasament n ordine lexicograc a ce respecta relat iile pe care si le
aminteste comisia.
Date de intrare
Fisier de intrare: COMPET.IN
Linia 1: N M - dou a numere naturale nenule, reprezent and num arul concurent ilor,
respectiv num arul relat iilor pe care si le aminteste comisia;
Liniile 2..M+1: i j - pe ecare din aceste M linii se aa cate dou a numere
naturale nenule i si j, av and semnicat ia: concurentul cu num arul de concurs i a
fost n clasament naintea concurentului cu num arul de concurs j.
Date de iesire
Fisier de iesire: COMPET.OUT
Linia 1: nr
1
nr
2
... nr
N
- pe aceast a linie se va scrie clasamentul sub forma
unui sir de numere naturale nenule, separate prin cate un spat iu, reprezent and
numerele de concurs ale concurent ilor, n ordine de la primul clasat la ultimul.
Restrict ii si precizari
1 < N 1000
se garanteaza corectitudinea datelor de intrare si faptul ca exista totdeauna
o solut ie.
Exemple
COMPET.IN COMPET.OUT COMPET.IN COMPET.OUT
3 1 1 2 3 4 2 2 1 3 4
1 2 2 1
3 4
10.4. COMPETIT IE DIFICIL
A 221
Timp maxim de execut ie: 1 secunda/test
10.4.1 Indicat ii de rezolvare - descriere solut ie *
Pentru ecare concurent se determin a num arul concurent ilor care se g asesc
n clasamentul nal n fat a lor. Dintre concurent ii care au n clasamentul nal n
fat a lor 0 (zero) concurent i se alege cel cu num arul de concurs cel mai mic. Acesta
este primul concurent din solut ie. Tuturor concurent ilor care l au n fat a lor pe
concurentul plasat n solut ie li se scade cate o unitate din num arul concurent ilor
pe care i au n fat a lor. Se repeta acest algoritm pana cand tot i concurent ii au
fost plasat i n solut ie.
10.4.2 Rezolvare detaliata
10.4.3 Codul sursa *
import java.io.*;
class competitie
{
static int n,m;
static int[] a;
static int[] b;
static int[] c;
static int[] inainte;
static boolean[] finalizat;
public static void main(String[] args) throws IOException
{
int i,j,igasit=-1;
StreamTokenizer st=new StreamTokenizer(new BufferedReader(
new FileReader("compet.in")));
PrintWriter out=new PrintWriter(new BufferedWriter(
new FileWriter("compet.out")));
st.nextToken();n=(int)st.nval;
st.nextToken();m=(int)st.nval;
a=new int[m+1];
b=new int[n+1];
c=new int[n+1]; // solutia
inainte=new int[n+1];
finalizat=new boolean[n+1];
222 CAPITOLUL 10. ONI 2001 CLASA A IX-A
for(i=1;i<=m;i++)
{
st.nextToken();a[i]=(int)st.nval; // a[i] < b[i]
st.nextToken();b[i]=(int)st.nval;
}
for(i=1;i<=m;i++) inainte[b[i]]++;
for(j=1;j<=n;j++)
{
for(i=1;i<=n;i++)
if((!finalizat[i])&&(inainte[i]==0))
{
finalizat[i]=true;
c[j]=i;
igasit=i;
break;
}
for(i=1;i<=m;i++)
if(a[i]==igasit) inainte[b[i]]--;
}
for(i=1;i<=n;i++) out.print(c[i]+" ");
out.close();
}
}
10.5 Cuvinte
prof. Maria Nit a si prof. Adrian Nit a, Oradea
Se considera o list a av and un num ar cunoscut de cuvinte. Din acest a
list a s-au ales dou a cuvinte oarecare. Se doreste transformarea primului cuvant n
cel de-al doilea, trecand prin cuvinte intermediare, existente n lista data. Trecerea
dintr-un cuvant n altul se poate face folosind urmatoarele operat ii: schimbarea,
adaugarea sau stergerea unui singur caracter.
Cerint a
Dandu-se o list a de cuvinte si dou a cuvinte din aceasta, g asit i cea mai scurt a
secvent a de operat ii care transforma primul cuvant n cel de-al doilea folosind
operat iile permise.
Date de intrare
Fisierul de intrare: CUVINTE.IN
Linia 1: N P Q - trei numere naturale nenule, reprezent and num arul cu-
vintelor din list a (N), pozit ia primului cuvant n list a (P), respectiv pozit ia celui
10.5. CUVINTE 223
de-al doilea cuvant n list a (Q);
Liniile 2..N+1: cuv ant - aceste N linii cont in ecare cate un cuvant, apart inand
listei.
Date de iesire
Fisier de iesire: CUVINTE.OUT
Linia 1: M - num ar natural, reprezent and num arul minim de pasi necesari
pentru a ajunge de la primul cuvant la al doilea;
Liniile 2..M+2: cuv ant
i
- pe aceste linii apar n ordine cuvintele dintr-o
secvent a ce respecta cerint a problemei (cate un cuvant pe linie), inclusiv primul
cuvant al secvent ei.
Restrict ii si precizari
2 N 100
1 M, P, Q 100
num arul maxim de caractere dintr-un cuvant este 100;
dac a nu exista solut ie, n sierul de iesire se va scrie num arul 0 (zero);
dac a sunt mai multe secvent e de lungime minima, n sier se va scrie una
singur a.
Exemple
CUVINTE.IN CUVINTE.OUT CUVINTE.IN CUVINTE.OUT
7 1 5 2 7 1 6 0
car car car
cer mar cer
cerc mare cerc
mar mar
mare mare
rosu rosu
inrosit inrosit
Timp maxim de execut ie: 2 secunde/test
10.5.1 Indicat ii de rezolvare - descriere solut ie *
Folosim un tablou bidimensional (a[i][j])
1i,jn
cu urmatoarea semnicat ie:
a[i][j] = 1 dac a se poate transforma cuvantul i n cuvantul j, si a[i][j] = 0 altfel.
Se parcurge n l at ime graful neorientat asociat, plec and de la primul cuvant, pana
cand se nt alneste al doilea cuvant sau nu mai sunt cuvinte care pot atinse prin
aceast a parcurgere.
224 CAPITOLUL 10. ONI 2001 CLASA A IX-A
10.5.2 Rezolvare detaliata
10.5.3 Codul sursa *
import java.io.*;
class Cuvinte
{
static int n,p,q;
static String[] cuvant=new String[101]; // cuvintele
static int[] coada=new int[101];
static int[] analizat=new int[101];
static int[] d=new int[101]; // distante catre p
static int[] pr=new int[101]; // predecesori
static int[][] a=new int[101][101]; // matrice de adiacenta
static PrintWriter out;
public static void main(String[] args) throws IOException
{
int i,j,k;
int ic,sc;
out=new PrintWriter(new BufferedWriter(new FileWriter("cuvinte.out")));
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("cuvinte.in")));
st.nextToken(); n=(int)st.nval;
st.nextToken(); p=(int)st.nval;
st.nextToken(); q=(int)st.nval;
for(i=1;i<=n;i++) { st.nextToken(); cuvant[i]=st.sval.toString(); }
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)
a[i][j]=a[j][i]=trece(cuvant[i],cuvant[j]);
// drum minim intre p si q
ic=0; sc=1; coada[ic]=p; // ic==sc ==> coada vida!
analizat[p]=1;
while(ic!=sc)
{
i=coada[ic]; ic++;
for(j=1;j<=n;j++)
{
if((analizat[j]==0)&&(a[i][j]==1))
{
10.5. CUVINTE 225
coada[sc]=j; sc++;
analizat[j]=1;
d[j]=d[i]+1;
pr[j]=i;
if(j==q) break;
}
}
if(analizat[q]==1) break;
}
out.println(d[q]);
drum(q);
out.close();
}
static void drum(int j)
{
if(pr[j]!=0) drum(pr[j]);
out.println(cuvant[j]);
}
static int trece(String x, String y) // lg egale sau diferenta=1
{
int k,dif;
if(Math.abs(x.length()-y.length())>1) return 0;
String xy;
if(x.length()<y.length()) {xy=x; x=y; y=xy;} // lg.x >= lg.y
int nx=x.length(), ny=y.length();
if(nx==ny)
{
dif=0;
for(k=0;k<nx;k++) if(x.charAt(k)!=y.charAt(k)) dif++;
if(dif==1) return 1; else return 0;
}
else // nx>ny
{
k=0;
while((k<ny)&&(x.charAt(k)==y.charAt(k))) k++;
if(k==ny) return 1;
else
{
k++;
while((k<ny)&&(x.charAt(k)==y.charAt(k-1))) k++;
if(k==ny) return 1; else return 0;
226 CAPITOLUL 10. ONI 2001 CLASA A IX-A
}
}
}
}
10.6 Grup
prof. Emanuela Cerchez si prof. Marinel Serban, Iasi
Administratorul ret elei cu N calculatoare de la SRI mparte, din mo-
tive strategice, aceste calculatoare n mai multe grupuri. De fapt, important este
doar num arul de grupuri si num arul de calculatoare din ecare grup, asa ca
mpart irea este descrisa prin sirul numerelor de calculatoare din ecare grup, or-
donat crescator.
Periodic, el procedeaz a la o nou a mpart ire pe grupe a calculatoarelor.
Dintre toate mpart irile posibile ale calculatoarelor n grupuri putem alege ca
urmatoare mpart ire doar aceea a carei descriere precede sau succede lexicograc
imediat mpart irii curente.
Not a:
Spunem ca sirul x
1
x
2
... x
p
precede lexicograc sirul y
1
y
2
... y
k
dac a:
a) exista un indice j, astfel ncat x
i
= y
i
pentru tot i indicii i < j si x
j
< y
j
sau
b) p < k si x
i
= y
i
pentru tot i indicii i p
Exemple
a) 3 7 2 5 precede lexicograc 3 7 4 1 6 2
b) 1 2 3 precede lexicograc 2
Cerint a
Dandu-se o mpart ire n grupe a celor N calculatoare, determinat i cele dou a
variante candidate pentru mpart irea urmatoare.
Date de intrare
Fisier de intrare: GRUP.IN
Linia 1: N k - numere naturale nenule, reprezent and num arul total (N) al
calculatoarelor din ret ea si num arul (k) de grupe.
Linia 2: g
1
g
2
. . . g
k
- num arul calculatoarelor din ecare grupa.
Date de iesire
Fisier de iesire: GRUP.OUT
p - num arul de grupe din mpart irea care precede lexicograc imediat
mpart irea data;
h
1
h
2
... h
p
- num arul de calculatoare din cele p grupe ale mpart irii prece-
dente;
u - num arul de grupe din mpart irea care succede lexicograc imediat
mpart irea data;
10.6. GRUP 227
t
1
t
2
... t
u
- num arul de calculatoare din cele u grupe alempart irii urmatoare;
Restrict ii si precizari
2 N 1000
g
1
+g
2
+... +g
k
= h
1
+h
2
+... +h
p
= t
1
+t
2
+... +t
u
= N
1 g
1
g
2
... g
k
; 1 h
1
h
2
... h
p
; 1 t
1
t
2
... t
u
;
1 < k < N
1 p, u N
Exemplu
GRUP.IN GRUP.OUT
14 3 3
2 6 6 2 5 7
2
2 12
Timp maxim de execut ie: 1 secunda/test
10.6.1 Indicat ii de rezolvare - descriere solut ie *
Fie g[i] num arul calculatoarelor din grupul i (1 i k.
Pentru secvent a precedent a (lexicograc):
Daca g[k 1] <= g[k]/2 atunci secvent a are k + 1 grupe. Grupul g[k] se
mparte n dou a grupuri (prima jumatate se plaseaza pe pozit ia k iar a doua
jumatate se plaseaza pe pozit ia k + 1 (daca g[k] este impar, grupul de pe pozit ia
k + 1 va avea cu un calculator mai mult decat grupul de pe pozit ia k).
Daca g[k 1] > g[k]/2 atunci se determin a cel mai mare indice i astfel ncat
g[i] 1 g[i 1]. Secvent a va avea i +1 grupe. Primele i 1 grupe de calculatoare
r aman neschimbate. Pe pozit ia i plas am g[i] 1 calculatoare iar pe pozit ia i + 1
restul calculatoarelor.
Pentru secvent a urmatoare (lexicograc):
Daca g[k 1] + 1 > g[k] 1 atunci secvent a are k 1 grupe. Primele k 2
grupe r aman neschimbate iar pe pozit ia k 1 se pun mpreuna calculatoarele de
pe pozit iile k 1 si k (din secvent a init iala).
Daca g[k 1] +1 g[k] 1 atunci primele k 2 grupuri r aman neschimbate
iar calculatoarele din grupurile k 1 si k (din secvent a init iala) se vor distribui n
grupuri de g[k 1] +1 calculatoare (cu except ia ultimului grup, eventual, care va
avea cel put in g[k1]+1 calculatoare dar nu mai mult de 2g[k1]+1 calculatoare).
10.6.2 Rezolvare detaliata
10.6.3 Codul sursa *
228 CAPITOLUL 10. ONI 2001 CLASA A IX-A
import java.io.*;
class Grup
{
static int n,k;
static int[] g;
public static void main(String[] args) throws IOException
{
int i,j,s,nge;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("grup.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("grup.out")));
st.nextToken(); n=(int)st.nval;
st.nextToken(); k=(int)st.nval;
g=new int[k+1];
for(i=1;i<=k;i++) { st.nextToken(); g[i]=(int)st.nval; }
if(g[k-1]<=g[k]/2)
{
out.println(k+1); // nr grupe din precedenta
for(j=1;j<=k-1;j++) out.print(g[j]+" ");
out.println((g[k]/2)+" "+(g[k]+1)/2);
}
else
{
s=g[k];
i=k-1;
while(g[i]-1<g[i-1]) {s+=g[i]; i--;}
out.println(i+1); // nr grupe din precedenta
for(j=1;j<i;j++) out.print(g[j]+" ");
out.println((g[i]-1)+" "+(s+1));
}
if(g[k-1]+1<=g[k]-1)
{
nge=(g[k]-1)/(g[k-1]+1);// nr grupe egale la sfarsit
out.println(k+nge-1); // nr grupe din urmatoarea
for(j=1;j<=k-2;j++) out.print(g[j]+" ");
for(j=1;j<=nge;j++) out.print((g[k-1]+1)+" ");
out.println(g[k-1]+1+(g[k]-1)%(g[k-1]+1));
}
else
{
10.6. GRUP 229
out.println(k-1); // nr grupe din urmatoarea
for(j=1;j<=k-2;j++) out.print(g[j]+" ");
out.println((g[k-1]+g[k]));
}
out.close();
}
}
230 CAPITOLUL 10. ONI 2001 CLASA A IX-A
Capitolul 11
ONI 2002 clasa a IX-a
11.1 Pentagon
lect. univ. Ovidiu Domsa, Alba Iulia
Intre dou a maluri ale unei v ai adanci s-a construit un pod suspendat
format din N bucat i de sc andur a, legate cu liane.
Vom considera ca sc andurile sunt numerotate de la 1 la N, ncepand de pe
malul pe care ne aam.
In timp unele bucat i de sc andur a s-au deteriorat, iar altele chiar au disparut.
11.2. POD 235
Pentru traversarea podului se stie ca:
se pot face pasi doar de lungime 1, 2 sau 3;
sc andurile deteriorate sunt nesigure, deci pe ele si de pe ele se pot face
doar pasi de lungime 1.
evident, nu se poate pasi pe o sc andur a care lipseste.
Cerint a:
Scriet i un program care s a determine num arul de modalit at i de traversare a
podului (mai exact, de a ajunge pe celalalt mal), precum si o solut ie de traversare,
dac a o astfel de solut ie exista.
Date de intrare:
Fisierul de intrare POD.IN are structura:
POD.IN Semnicat ie
N Numarul total de sc anduri
k s
1
s
2
... s
k
Numarul de sc anduri lipsa si numerele lor de ordine
h d
1
d
2
... d
h
Numarul de sc anduri deteriorate si numerele lor de ordine
Date de iesire:
Fisierul de iesire POD.OUT va cont ine pe prima linie valoarea -1 dac a nu
este posibil s a traversam podul, respectiv num arul de posibilitat i de a traversa
podul, dac a aceasta este posibil.
In cazul n care exista solut ii, pe cea de a doua linie va asata o astfel de
solut ie, prin indicarea, n ordine, a sc andurilor pe care se paseste, sub forma:
POD.OUT Semnicat ie
Nr Numarul total de posibilitat i
p
1
p
2
... p
m
Solut ia determinata, prin indicarea n ordine a sc andurilor
pe care se paseste
Restrict ii si precizari:
3 N 300
0 k, h N
{s
1
, s
2
, ..., s
k
} {2, ...N},
{d
1
, d
2
, ..., d
h
} {1, 2, ...N};
{s
1
, s
2
, ..., s
k
} {d
1
, d
2
, ..., d
h
} =
Nr are cel mult 80 de cifre.
Exemple:
pod.in pod.out pod.in pod.out pod.in pod.out
5 24 10 48 6 -1
0 3 2 2 7 3 6 8 2 2 4
0 1 5 1 3
Timp maxim de execut ie: 1 secunda/test
236 CAPITOLUL 11. ONI 2002 CLASA A IX-A
11.2.1 Indicat ii de rezolvare - descriere solut ie *
Solut ie prezentat a n GInfo 12/6
Rezolvarea problemei se bazeaza pe o variant a simpla a metodei programarii
dinamice. Se observa foarte usor ca num arul de posibilitat i de a ajunge pe cea
de-a i-a sc andur a depinde doar de num arul de posibilitat i de a ajunge pe cele trei
sc anduri aate n fat a ei.
Vom nota cu t
i
num arul de posibilitat i de a ajunge pe cea de-a i-a sc andur a.
Vom considera malul opus ca ind cea de-a (N + 1)-a sc andur a, unde N este
num arul sc andurilor care formeaz a podul.
Solut ia problemei va data de valoarea t
N+1
.
In cazul n care cea de-a i-a sc andur a lipseste, pe ea nu se poate ajunge, deci
vom avea t
i
= 0.
N
i=1
i S.
Valoarea N se obt ine rezolv and ecuat ia de gradul II S
N
= S (vom avea
S
N
S +N) si rotunjind prin adaos r adacina pozitiva obt inuta. Avem:
N(N+1)
2
= S N
2
+N 2 S = 0 N =
1+8S1
2
Asadar, valoarea N este
_
1+8S1
2
_
. Datorit a faptului ca N este cea mai
mica valoare pentru care suma atinge sau depaseste valoarea S, solut ia problemei
nu poate data de nici un num ar N
< N.
.
Suma totala a elementelor carora trebuie s a le e modicat semnul este
D
N
/2. Prin modicarea semnului unui element, valoarea expresiei scade cu dublul
acestui element, deci avem S
N
D
N
/2 2 = S.
Fie x = D
N
/2 (suma totala a elementelor care trebuie sc azute). Deoarece
N
2
.
11.3. SUMA 247
Asadar, valoarea x poate obt inuta aleg and doar dou a numere cuprinse ntre 1 si
N
vom sc adea N
si N
In nal, vom alege discul (sau axa Oy) pentru care coordonata orizontala
a centrului noului disc este maxima si putem arma ca discul i ajuge n aceast a
pozit ie.
Daca discul i va atinge un disc anterior j, atunci discurile cu numerele de
ordine cuprinse ntre j + 1 si i 1 sunt dispensabile.
Dup a ce vom lua n considerare toate cele N discuri, vom putea determina
numerele de ordine ale tuturor discurilor dispensabile.
260 CAPITOLUL 11. ONI 2002 CLASA A IX-A
In nal vom verica dac a exista discuri introduse la sfarsit care sunt dis-
pensabile. Pentru aceasta vom determina l at imea gurii si ultimul disc care o
inuent eaz a. Toate discurile introduse dupa acest disc sunt dispensabile.
Pentru determinarea coordonatei orizontale x
i
a centrului unui disc i care
atinge un disc j avem nevoie de coordonata orizontala x
j
a centrului discului j,
precum si de razele r
i
si r
j
ale celor dou a discuri. Daca aceste trei valori sunt
cunoscute, se poate folosi urmatoarea formula pentru a determina coordonata
orizontala a centrului discului j:
x
j
= x
i
+
_
(r
i
+r
j
)
2
(r
i
r
j
)
2
.
Analiza complexitat ii
Pentru ecare disc i care este introdus, se determin a posibila coordonat a x
i
datorata atingerii cu toate cele i1 discuri inserate anterior. Pentru cele N discuri
se vor determina, n total, 0 +1 +2 +... +(N 1) = N(N 1)/2 coordonate, deci
ordinul de complexitate al acestei operat ii este O(N
2
.
La ecare pas, pot marcate ca dispensabile cel mult toate discurile inserate
anterior, asadar ordinul de complexitate al acestei operat ii este tot O(N
2
).
Determinarea l at imii gurii si a cercurilor dispensabile de la sfarsitul secvent ei
necesita a singur a parcurgere a sirului care pastreaza coordonatele centrelor dis-
curilor, ceea ce implica ordinul de complexitate O(N).
Asarea cercurilor dispensabile precumsi citirea razelor cercurilor sunt operat ii
care se efectueaza n timp liniar (O(N)), necesitand o simpla parcurgere a unor
siruri.
k
i=1
C
i
26
.
n
i=1
C
k1
26i
cuvinte valide de care ncep cu o litera mai mica.
In acest moment stim num arul de ordine minim al unui cuvant care ncepe
cu prima litera a cuvantului dat.
Pentru a doua litera vom proceda ntr-o maniera asem anatoare. Singura
diferent a este data de faptul ca a doua litera trebuie s a e strict mai mare dec at
prima. Asadar, dac a prima litera este cea de-a n-a a alfabetului, iar a doua este
264 CAPITOLUL 11. ONI 2002 CLASA A IX-A
cea de-a m-a, atunci vom avea
m1
i=n+1
C
k2
26i
cuvinte care au pe prima pozit ia
aceeasi litera, iar pe cea de-a doua pozit ie o litera mai mica.
Procedeul va continua pentru ecare litera n parte.
In cazul n care litera curent a este cea de-a p-a a cuvantului, este a m-a a
alfabetului, iar litera anterioar a este a n-a a alfabetului, num arul de cuvite care
au pe primele p 1 pozit ii aceleasi litere ca si cuvantul dat, iar pe cea de-a p-a o
litera mai mica este dat de formula
m1
i=n+1
C
kp
26i
.
Adunand toate valorile obt inute pe parcurs vom obt ine num arul cuvintelor
care se aa naintea cuvantului dat. Adunand 1 la aceast a valoare, vom obt ine
num arul de ordine al cuvantului.
Analiza complexitat ii
Pentru a analiza complexitatea acestui algoritm va trebui s a preciz am faptul
ca num arul literelor din alfabet este constant, deci nu poate interveni n exprimarea
ordinului de complexitate. Acesta va stabilit doar n funct ie de lungimea k a
cuvantului.
Init ial se calculeaz a suma
k
i=1
C
i
26
, operat ie realizabila n timp liniar, av an
n vedere observat ia anterioar a. Asadar, primul pas al algoritmului are ordinul de
complexitate O(k).
Pentru ecare litera a cuvantului se calculeaz a suma
m1
i=n+1
C
k2
26i
, unde
variabilele au semnicat ia prezentata anterior. Numarul de litere este implicat n
determinarea valorii combin arii. Asadar, calculul combin arii se realizeaza n timp
liniar. Numarul de combin ari calculate nu depinde de lungimea cuvantului, deci
ordinul de complexitate al calcularii acestei sume este O(k).
In sier nu sunt mai mult de 200.000 de cuvinte, iar caracterele sunt literele
mici ale alfabetului englez.
Datele de intrare se presupun ca ind corecte.
Exemplu
seti.in seti.out
abcdefghij aaaa
aaaa aabc
fgaa fgaa
aabc iihf
iihf
Timp de execut ie: 1 sec/test
12.1.1 Indicat ii de rezolvare - descriere solut ie *
Solut ie prezentat a de Mihai Stroe, GInfo nr. 13/6
Rezolvarea problemei const a n realizarea unei metode de trecere de la cu-
vintele de 4 litere la numerele de cel mult 4 cifre. Avand o astfel de metoda, toate
cuvintele se vor transforma n numere cuprinse ntre 0 si 9999.
Numerele nu vor memorate, n schimb se va folosi un tablou cu 10.000
de elemente, ecare element reprezent and num arul de aparit ii al unui cuvant din
sier.
In continuare pana la sfarsitul sierului sunt linii ce descriu numerele de
ordine ale copiilor care se ridic a unul cate unul de pe scaune si par asesc jocul.
Date de iesire
Fisierul de iesire scaune.out cont ine nc linii, ecare linie cont inand pozit ia
init iala de asteptare a copilului si pozii a ocupat a, separate printr-un spat iu.
Liniile de iesire trebuie s a e n aceeasi ordine ca cele din sierul de intrare.
In cazul metodei mai rapide, calcularea distant ei pentru tot i copiii pana la
scaunul liber are complexitatea O(NC). Aceeasi complexitate au si operat iile de
alegere a minimului P dintre aceste distant e, respectiv de avansare a tuturor copi-
ilor cu P pozit ii.
Ordinul de complexitate al algoritmului de rezolvare a acestei probleme este
O(NC NS NC) pentru prima variant a, respectiv O(NC NC) pentru cea de-a
doua.
12.2.2 Rezolvare detaliata
12.2.3 Codul sursa *
Diferent a de timp ntre cele dou a variante este mica!
import java.io.*;
class Scaune1
{
static int ns, nc;
static int[] pozInitiala;
static int[] pozFinala;
12.2. SCAUNE 275
static boolean[] asezat;
public static void main(String[]args) throws IOException
{
int i,j,k,nca=0; // nca=nr copii asezati
long t1,t2;
t1=System.currentTimeMillis();
PrintWriter out = new PrintWriter(
new BufferedWriter(new FileWriter("scaune.out")));
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("scaune.in")));
st.nextToken(); ns=(int)st.nval;
st.nextToken(); nc=(int)st.nval;
asezat=new boolean[nc+1];
pozInitiala=new int[nc+1];
pozFinala=new int[nc+1];
for(k=1;k<=nc;k++)
{
st.nextToken();
pozInitiala[k]=pozFinala[k]=(int)st.nval;
}
while(st.nextToken()!=st.TT_EOF)
{
k=(int)st.nval; // scaunul k este liber
i=esteLaPozitia(k);
while((nca<nc)&&(i==0)) { misca(); i=esteLaPozitia(k); }
pozFinala[i]=k;
asezat[i]=true;
nca++;
}
for(j=1;j<=nc;j++)
if(asezat[j]) out.println(pozInitiala[j]+" "+pozFinala[j]);
else out.println(pozInitiala[j]+" "+0);
out.close();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}//main
static void misca()
{
int i;
for(i=1;i<=nc;i++)
276 CAPITOLUL 12. ONI 2003 CLASA A IX-A
if(!asezat[i])
{
pozFinala[i]++;
if(pozFinala[i]==ns+1) pozFinala[i]=1;
}
}
static int esteLaPozitia(int k)
{
int i,copil=0;
for(i=1;i<=nc;i++)
if(!asezat[i]&&(pozFinala[i]==k)) { copil=i; break; }
return copil;
}
}//class
Pentru a doua varianta se calculeaz a distant ele pana la scaunul liber pentru
ecare copil r amas neasezat.
import java.io.*;
class Scaune2
{
static int ns, nc;
static int[] pozInitiala;
static int[] pozFinala;
static boolean[] asezat;
static int[] d;
public static void main(String[]args) throws IOException
{
int i,j,k;
long t1,t2;
t1=System.currentTimeMillis();
PrintWriter out = new PrintWriter(
new BufferedWriter(new FileWriter("scaune.out")));
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("scaune.in")));
st.nextToken(); ns=(int)st.nval;
st.nextToken(); nc=(int)st.nval;
asezat=new boolean[nc+1];
d=new int[nc+1];
pozInitiala=new int[nc+1];
pozFinala=new int[nc+1];
12.2. SCAUNE 277
for(k=1;k<=nc;k++)
{
st.nextToken();
pozInitiala[k]=pozFinala[k]=(int)st.nval;
}
while(st.nextToken()!=st.TT_EOF)
{
k=(int)st.nval; // scaunul k este liber
i=esteLaPozitia(k);
pozFinala[i]=k;
asezat[i]=true;
}
for(j=1;j<=nc;j++)
if(asezat[j]) out.println(pozInitiala[j]+" "+pozFinala[j]);
else out.println(pozInitiala[j]+" "+0);
out.close();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}//main
static int esteLaPozitia(int k)
{
int i,min,imin;
for(i=1;i<=nc;i++)
if(!asezat[i])
if(pozFinala[i]<=k) d[i]=k-pozFinala[i];
else d[i]=k+ns-pozFinala[i];
imin=0; min=ns+1;
for(i=1;i<=nc;i++)
if(!asezat[i])
if(d[i]<min){ min=d[i]; imin=i; }
for(i=1;i<=nc;i++)
if(!asezat[i])
{
pozFinala[i]=pozFinala[i]+min;
if(pozFinala[i]>ns) pozFinala[i]=pozFinala[i]-ns;
}
return imin;
}
}//class
278 CAPITOLUL 12. ONI 2003 CLASA A IX-A
12.3 Circular
Unele numere naturale sunt formate doar din cifre distincte nenule.
Dintre acestea, unele, numite numere circulare, au urmatoarea proprietate:
pornind de la prima cifra si num ar and spre dreapta, dupa cifra, at atea cifre cat
indic a aceasta, se determin a o nou a cifra. Procedand la fel si pentru aceasta si
pentru toate cele care urmeaz a se va ajunge din nou la prima cifra.
Daca toate cifrele au fost vizitate exact o data, num arul se numeste circular.
De exemplu num arul
1894256
este num ar circular deoarece:
are numai cifre distincte
nu cont ine cifra 0
pornind de la 1 obt inem, pe r and: 8, 9, 2, 6, 5, 4, 1
Cerint a
Scriet i un program care, pentru un N dat, determin a cate numere circulare
sunt mai mici sau egale cu N, precum si cel mai mare num ar circular mai mic sau
egal cu N.
Date de intrare
Pe prima linie a sierului de intrare circular.in se aa num arul natural N.
Date de iesire
Fisierul de iesire circular.out cont ine o singur a linie, pe care se aa num arul
de numere circulare mai mici ca N precum si num arul circular maxim cerut, sep-
arate printr-un spat iu.
Daca nu exista nici un num ar circular mai mic ca N, n sierul de iesire se
vor asa dou a valori 0 separate printr-un spat iu.
Restrict ii
10 N < 10.000.000
Exemplu
circular.in circular.out Semnicat ie
1894250 347 1849625 Exist a 347 numere circulare mai mici dac at
1894250 cel mai mare dintre acestea ind
num arul 1849625
Timp de execut ie: 1 sec/test
12.3.1 Indicat ii de rezolvare - descriere solut ie *
Solut ie prezentat a de Mihai Stroe, GInfo nr. 13/6
12.3. CIRCULAR 279
O rezolvare foarte buna a acestei probleme se bazeaza pe faptul ca exista
foarte put ine numere circulare ntre 10 si 10.000.000. Acestea pot generate n
timpul concursului, obt inandu-se un sier cu toate numerele circulare, cate 10 pe
linie si separate prin virgula. Acest sier poate transformat usor ntr-un vector
de constante care poate folosit de un program Pascal sau C/C++ care, astfel
cont ine toate numerele circulare. Acest program va citi valoarea lui N, apoi va
rezolva cerint ele parcurgand vectorul de constante. Deci, concurentul va elabora
dou a programe: cel de generare a numerelor circulare si cel care, folosindu-le,
rezolv a cerint ele problemei.
Pentru generarea numerelor circulare se poate folosi un ciclu for pana la
10.000.000, n cadrul caruia se testeaz a, pe r and, pentru ecare num ar dac a este
circular. Un mod simplu de a realiza aceast a testare este de a transforma num arul
ntr-un vector de cifre, prin mpart iri succesive la 10 cu salvarea restului.
Se observa ca se vor obt ine cifrele num arului n ordine inversa; este foarte
usor s a se restabileasca ordinea corecta prin inversarea primei cifre cu ultima, a
celei de-a doua cu penultima etc.
Pentru un num ar reprezentat ca un vector de cifre se poate verica foarte usor
dac a este format din cifre distincte si nu cont ine cifra 0; pentru condit ia r amasa se
va num ara spre dreapta, iar pozit iile pe care se opreste num ararea vor marcate
cu 0. Daca la un moment dat se va ajunge pe o pozit ie marcat a cu 0, far a a se
marcat n prealabil toate pozit iile, atunci num arul nu este circular.
O metoda mai buna si mai rapida ar consta n generarea tuturor vectorilor
de cifre distincte nenule de cel mult 7 cifre, folosind metoda backtracking.
O alta metoda, si mai rapida, ar consta n generarea directa a numerelor
circulare, folosind o alta variant a a metodei backtracking. Astfel, dup a ncercarea
de a folosi cifra C
1
pe prima pozit ie, se va trece la pozit ia 1 + C
1
(de fapt se vor
face C
1
avans ari spre dreapta) si se va continua de acolo; dac a acolo se va folosi
cifra C
2
, se avanseaza nca C
2
pozit ii spre dreapta etc.
La ecare pas din backtracking se folosesc cifrele cuprinse ntre 1 si 9, care
nu au fost folosite anterior; dac a avansarea spre dreapta duce ntr-o pozit ie deja
completata si mai sunt pozit ii libere, num arul n construct ie nu poate circular
si se revine la cifra precedent a.
Analiza complexitat ii
Pentru aceast a problema, complexitatea rezolv arii este data de num arul M
de numere circulare, deci solut ia ruleaza instantaneu, deci ordinul de complexitate
al acesteia ar O(log
2
M), n cazul n care se foloseste o cautare binara.
Deoarece M este o constant a, ordinul de complexitate al solut iei este O(1).
Complexitatea metodei de generare a numerelor circulare depinde de metoda
folosita.
12.3.2 Rezolvare detaliata
280 CAPITOLUL 12. ONI 2003 CLASA A IX-A
12.3.3 Codul sursa *
import java.io.*; // Timp = 18sec pentru n=9.999.999 (448 --> 9.682.415)
class Circular1 // Timp = 1.8sec pentru n=1.000.000
{ // Timp = 0.9sec pentru n= 555.555 (3 teste peste !!!)
static int n, nnc=0,ncmax=0;
static int[] a=new int[7]; // vectorul cifrelor
static int[] aa=new int[7]; // traseu!
static int[] fc=new int[10];// frecventa cifrelor
static int nc;
public static void main(String[]args) throws IOException
{
int k;
long t1,t2;
t1=System.currentTimeMillis();
PrintWriter out = new PrintWriter(
new BufferedWriter(new FileWriter("circular.out")));
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("circular.in")));
st.nextToken(); n=(int)st.nval;
for(k=12;k<=n;k++)
if(esteCircular(k)) { nnc++; ncmax=k; }
out.println(nnc+" "+ncmax);
out.close();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}//main
static boolean esteCircular(int k)
{
int i,j;
int c; // cifra
nc=0;
for(i=0;i<=9;i++) fc[i]=0;
while(k!=0) {c=k%10; a[nc]=c; fc[c]++; k=k/10; nc++;}
if(fc[0]>0) return false;
for(i=1;i<=9;i++) if(fc[i]>1) return false;
for(i=0;i<nc/2;i++) {c=a[i]; a[i]=a[nc-1-i]; a[nc-1-i]=c;}
for(i=0;i<nc;i++) aa[i]=a[i];
12.3. CIRCULAR 281
j=0;
for(i=1;i<=nc;i++)
if(aa[j]==0) return false; else { aa[j]=0; j=(j+a[j])%nc; }
if(j==0) return true; else return false;
}
}//class
import java.io.*;
class Circular2
{
static int n, nnc=0,ncmax=0;
static int[] x=new int[7];
static int[] a=new int[7];
static int[] aa=new int[7];
static int ncn; // nr cifrelor lui n
static int nc; // nc=2, ..., ncn (lg numerelor generate)
public static void main(String[] args) throws IOException
{
long t1,t2;
t1=System.currentTimeMillis();
PrintWriter out = new PrintWriter(
new BufferedWriter(new FileWriter("circular.out")));
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("circular.in")));
st.nextToken(); n=(int)st.nval;
int k=n;
ncn=0;
while(k!=0) {k=k/10; ncn++;}
for(nc=2;nc<=ncn;nc++) f(0);
out.println(nnc+" "+ncmax);
out.close();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}
static void f(int k)
{
boolean ok;
int i,j;
for(i=1;i<=9;i++) // pun valoarea i pe pozitia k in vectorul a
{
282 CAPITOLUL 12. ONI 2003 CLASA A IX-A
ok=true;
if(k>0)
for(j=0;j<k;j++) if(i==x[j]) {ok=false; break;}
if(!ok) continue;
x[k]=i;
if(k<nc-1) f(k+1); else afisv();
}
}
static void afisv()
{
if(!esteCircular(x)) return;
if(numar(x)>n) return;
nnc++;
ncmax=numar(x);
//System.out.print(nnc+" : ");
//for(int i=0; i<=nc-1; i++) System.out.print(x[i]);
//System.out.println();
}
static int numar(int[] x)
{
int nx=x[0];
for(int i=1;i<=nc-1;i++) nx=nx*10+x[i];
return nx;
}
static boolean esteCircular(int[] x)
{
int i,j;
for(i=0;i<nc;i++) a[i]=aa[i]=x[i];
j=0;
for(i=1;i<=nc;i++)
if(aa[j]==0) return false; else { aa[j]=0; j=(j+a[j])%nc; }
if(j==0) return true; else return false;
}
}
12.4 Criptare
12.4. CRIPTARE 283
Mircea si Vasilic a vor s a-si trimit a mesaje pe care alt ii sa nu le nt eleaga. Au
citit ei despre spioni si modalit at i de a scrie mesaje si, n nal, au imaginat un mod
de criptare a unui mesaj care foloseste cuvant cheie (le-a placut lor denumirea
asta :-) ).
Aleg andu-si un cuvant cheie format numai din litere distincte, ei num ar a
literele acestuia si mpart mesajul n grupe de lungime egal a cu num arul de litere
ale cuvantului cheie, si le aseaza una sub alta. Desigur, se poate nt ampla ca ultima
grupa s a e incomplet a, asa ca o completeaza cu spat ii.
Apoi numeroteaz a literele cuvantului cheien ordinea aparit iei lor n alfabetul
englez.
i
k=1
s
i
.
Pentru ca PAM s a poat a efectua turul, este necesar ca suma cantitat ii de
benzina acumulate s a e mai mare sau egal a cu 0, deci s
n
= 0.
12.5. MASINA 289
Rezolvarea problemei const a n a g asi un x astfel ncat
c
x
0, c
x
+c
x1
0, ..., c
x
+c
x+n1
0,
adica
s
x
s
x1
0, s
x+1
s
x1
0,..., s
x+n1
s
x1
0.
Un candidat viabil este pozit ia m n pentru care s
m
este minim.
In plus, ntr-o formul a propozit ional a pot s a apar a si paranteze care stabilesc
ordinea operat iilor.
In lipsa parantezelor, operatorii n ordinea priorit at ii lor sunt
& | => <=>.
In formulele de forma A
1
opA
2
op...bfopA
K
asociat iile se fac de la dreapta
la stanga (adica A
1
op(A
2
op(...opA
K
)...)), unde op este unul dintre &, |, =>
sau <=> si A
i
sunt formule propozit ionale, cu i de la 1 la K.
In sierul de iesire sir.out se va asa, pe prima linie, num arul cerut urmat
de caracterul sfarsit de linie.
Restrict ii:
3 n 20000
3 k n
Exemple:
sir.in sir.out
3 1
4 3
5 7
Timp execut ie: 1 sec/test
13.5.1 Indicat ii de rezolvare - descriere solut ie *
Solut ia ocial a
Notand cu r diferenta dintre doi tereni consecutivi constat am ca pentru r = 1
se pot construi urmatoarele submult imi, siruri cu proprietea ceruta, de lungime 3:
{1, 2, 3}, {2, 3, 4}, ..., {n 2, n 1, n}.
Cele de lungime superioara se construiesc adaugand elemente pe cele deja
obt inute. Numarul lor va
n2
i=1
i.
Similar pentru r = 2 obt inem urmatoarele submult imi, siruri de lungime 3:
{1, 3, 5}, {2, 4, 6}, ..., {n4, n2, n} sau {n5, n3, n1} functie de paritatea lui n .
13.6. SNIPERS 317
Cele de lungime superioara se construiesc adaugand elemente pe acestea.
Numarul lor este o suma te tipul precedent.
Se continua astfel pana la r = n/2, valoarea maxima a lui r.
13.5.2 Rezolvare detaliata
13.5.3 Codul sursa *
import java.io.*;
class sir
{
public static void main(String []args) throws IOException
{
int ns=0,n=19999,r,k,i;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("sir.in")));
PrintWriter out=new PrintWriter(new BufferedWriter(
new FileWriter("sir.out")));
st.nextToken(); n=(int)st.nval;
ns=0;
for(r=1;r<=(n-1)/2;r++)
for(k=3;k<=(n-1+r)/r;k++)
ns=ns+n-(k-1)*r;
System.out.println(ns);
out.println(ns);
out.close();
}
}
13.6 Snipers
Se spune ca n timpul r azboiului cu gnomii, trolii au trimis n trag aori de elit a
s a lichideze cele n capetenii inamice.
Din fericire capeteniile inamice erau plasate n camp deschis, iar trag atorii
au reusit s a se plaseze n zon a far a s a e observat i.
Cand s a e data comanda de tragere s-a constatat ca nu se transmisese
ecarui trag ator ce capetenie s a mpuste, iar dac a doi trag atori ar tras n aceeasi
capetenie sau traiectoriile razelor ucigase s-ar intersectat, atunci ar sc apat cel
318 CAPITOLUL 13. ONI 2004 CLASA A IX-A
put in o capetenie care ar putut duce r azboiul pana la cap at, iar trolii ar fost
nvinsi.
Deoarece capeteniile aveau capacitatea de a deveni invizibile oric and doreau
(pe o perioad a nelimitata), trebuiau lichidate simultan, altfel ...
Istoria ne spune ca trolii au nvins deoarece comandantul lor a reusi ca n
mai put in de o secunda s a transmit a ecarui trag ator n ce capetenie s a traga.
Voi putet i face asta?
Cerint a
Scriet i un program care, citind pozit iile trag atorilor si a capeteniilor, deter-
mina capetenia n care trebuie s a traga ecare trag ator.
Date de intrare
Fisierul de intrare snipers.in cont ine
pe prima sa linie num arul n
pe urmatoarele n linii se aa perechi de numerentregi, separate prin spat iu,
ce reprezint a coordonatele trag atorilor urmate de
alte n perechi de numere ntregi ce reprezint a coordonatele capeteniilor
(abscisa si ordonat a).
Date de iesire
Fisierul de iesire snipers.out cont ine n linii.
Pe linia i a sierului se aa num arul capeteniei t intite de trag atorul i
(i = 1...n).
Restrict ii si precizari
0 < n < 200
Coordonatele sunt numere ntregi din intervalul [0, 50000]
Raza ucigas a a oric arei arme se opreste n t inta sa.
In desen, avem
un prim segment elementar orizontal (consum = 1J), apoi
spre Nord dou a segmente elementare (consum: 1 + 2 = 3J)
urmeaz a 3 segmente spre Est (consum: 1 + 1 + 1 = 3J) si
ultima port iune de un segment vertical (consum: 1J).
Total consum energie: 1 + 3 + 3 + 1 = 8J.
Cerint a
Scriet i un program care citeste x si y si care aseaza num arul minim de J
consumat i pentru tot drumul de la pozit ia (0, 0) la pozit ia (x, y), merg and doar n
direct iile precizate.
Date de intrare
Fisierul de intrare romeo.in cont ine numerele x si y pe prima linie, separate
de un spat iu.
Date de iesire
14.2. ROMEO 335
Fisierul de iesire romeo.out cont ine o singur a linie cu num arul de J consumat i
pentru distant a totala parcurs a din pozit ia de plecare pana n cea nala.
Restrict ii si precizari
x si y sunt numere naturale;
0 x, y 40000
Fiecare linie din sierul de intrare si din sierul de iesire se ncheie cu
marcaj de sfarsit de linie.
Exemplu
romeo.in romeo.out
3 2 5
0 1 2 3
2
1
0
Explicat ie
Datele de intrare indic a un oras ca n desen.
Un drum posibil (el nu este unic) este dat de linia ngrosata.
Primul segment vertical consum a 1J, port iunea orizontala consum a 3J si
ultimul segment vertical (cel din dreapta), nca 1J, deci vom asa num arul 5, care
reprezint a 1J+3J+1J=5J.
Timp maxim de execut ie/test: 1 sec sub Windows si 1 sec sub Linux
14.2.1 Indicat ii de rezolvare - descriere solut ie *
Solut ia ocial a, profesor Dan Grigoriu
Solut ia descrisa este realizata didactic si se bazeaza pe un calcul algebric
simplu; solut ia nu cont ine structuri repetive.
Energia pentru segmentele orizontale este n toate cazurile aceeasi: X.
Problema r amane pentru energia consumata cu segmentele verticale.
Analiz am dou a cazuri:
1) Daca X Y 1, atunci se poate adopta un drum cu consum minim de
energie merg and pe un zig-zag cu segmente elementare, ncepand cu direct a spre
Nord, pana la strada orizontala a destinat iei, dupa care (daca este cazul), se merge
pe acea strada pana la destinat ie, pe orizontala, ca n desenul alaturat.
336 CAPITOLUL 14. ONI 2005 CLASA A IX-A
Drumul prezentat nu este unic.
Bilant ul pentru un astfel de drum (n exemplu: X = 4 si Y = 3) este:
(X +Y )J.
2) Daca X < Y 1, atunci vom avea si port iuni verticale mai mari decat un
segment elementar pe verticala. Cu cat o asemenea port iune este mai lunga, cu
at at energia consumata este mai mare. De aceea, vom ncerca s a avem port iuni
verticale de lungimi cat mai mici, chiar dac a sunt mai multe, lungimea lor totala
ind aceeasi: Y .
Numarul de port iuni verticale va X+1, adica vom merge vertical pe ecare
strada verticala o port iune, pentru a avea cat mai multe port iuni verticale (deci si
mai mici).
Fie Z = [Y/(X+1)] = lungimea unei port iuni verticale (num arul de segmente
elementare). Port iunile verticale vor avea toate lungimea Z, dac a (X + 1)|Y , sau
Z si Z + 1, n caz contrar. Pentru acest caz, e M = num arul de segmente de
marime Z si N = num arul de segmente de marime Z + 1.
Se va rezolva sistemul:
M +N = X + 1 (1)
M Z +N (Z + 1) = Y (2)
Semnicat ia ecuat iilor:
(1): (num arul de port iuni verticale de lungime Z) + (num arul de port iuni
verticale de lungime Z + 1) = (num arul total de port iuni verticale, adica X + 1).
(2): (lungimea totala a port iunilor de lungime Z) + (lungimea totala a
pot iunilor de lungime Z + 1) = (distant a totala de parcurs pe verticala, adica
Y ).
Odat a obt inute M si N, energia pe verticala se va calcula ca ind suma dintre
E1 = energia pentru cele M port iuni de lungime Z si E2 = energia pentru cele N
port iuni de lungime Z + 1.
E1 +E2 = M (1 + 2 + 3 + +Z) +N (1 + 2 + 3 + + (Z + 1)).
14.2. ROMEO 337
Mai jos, avem conform desenului:
X = 4 si Y = 12.
Atunci: Z = [Y/(X + 1)] = [12/(4 + 1)] = [12/5] = 2
Sistemul devine:
(1) M +N = 4 + 1
(2) M 2 +N (2 + 1) = 12,
adica
M +N = 5
M 2 +N (2 + 1) = 12
cu solut ia:
M = 3 si N = 2
Cu acestea, E1 si E2 devin:
E1 = M (1 + +Z) = 3 (1 + 2) = 9J
E2 = N (1 + +Z + 1) = 2 (1 + 2 + 3) = 12J
Bilant :
Total energie pe verticala: E1 +E2 = 9 + 12 = 21J.
Total energie pe orizontala: X = 4J
Total energie pentru tot drumul: 21 + 4 = 25J
Observat ie
Orasul este de forma patrata, dar n desen apare doar o parte din el (cea
interesant a pentru noi).
338 CAPITOLUL 14. ONI 2005 CLASA A IX-A
14.2.2 Rezolvare detaliata *
Rezolvarea sistemului conduce la n = y (x+1)z si m = x+1 y +(x+1)z
unde z =
_
y
x+1
_
iar energia totala este
m
z(z + 1)
2
+n
(z + 1)(z + 2)
2
+x.
14.2.3 Codul sursa *
import java.io.*;
class Romeo
{
public static void main(String[] args) throws IOException
{
int x,y;
int z,m,n,e;
PrintWriter out = new PrintWriter(
new BufferedWriter(new FileWriter("romeo.out")));
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("romeo.in")));
st.nextToken(); x=(int)st.nval;
st.nextToken(); y=(int)st.nval;
if(x>=y-1) e=x+y;
else
{
z=y/(x+1);
n=y-(x+1)*z;
m=x+1-y+(x+1)*z;
e=m*z*(z+1)/2+n*(z+1)*(z+2)/2+x;
}
out.println(e);
out.close();
}
}
14.3 Seceta
lect. Ovidiu Domsa
Gr adinile roditoare ale B ar aganului sufera anual pierderi imense din
cauza secetei. Cautatorii de apa au g asit n fant ani din care doresc s a alimenteze n
gr adini. Fie G
i
, F
i
, i = 1, ..., n puncte n plan reprezent and puncte de alimentare
14.3. SECETA 339
ale gr adinilor si respectiv punctele n care se aa fant anile. Pentru ecare punct
se dau coordonatele ntregi (x, y) n plan.
Pentru a economisi materiale, leg atura dintre o gr adina si o fant ana se rea-
lizeaza printr-o conduct a n linie dreapta. Fiecare fant ana alimenteaza o singur a
gr adina. Consiliul Judet ean Galat i plateste investit ia cu condit ia ca lungimea to-
tala a conductelor s a e minima.
Fiecare unitate de conduct a cost a 100 lei noi (RON).
Cerint a
Sa se determine m, costul minim total al conductelor ce leag a ecare gr adina
cu exact o fant ana.
Date de intrare
Fisierul de intrare seceta.in va cont ine:
Pe prima linie se aa num arul natural n, reprezent and num arul gr adinilor
si al fant anilor.
Pe urmatoarele n linii se aa perechi de numere ntregi G
x
G
y
, separate
printr-un spat iu, reprezent and coordonatele punctelor de alimentare ale gr adinilor.
Pe urmatoarele n linii se aa perechi de numere ntregi F
x
F
y
, separate
printr-un spat iu, reprezent and coordonatele punctelor fant anilor.
Date de iesire
Fisierul de iesire seceta.out va cont ine:
m un num ar natural reprezent and partea ntreag a a costului minim total
al conductelor.
Restrict ii si precizari
1 < n < 13
0 Gx, Gy, Fx, Fy 200
Nu exista trei puncte coliniare, indiferent dac a sunt gr adini sau fant ani
Orice linie din sierele de intrare si iesire se termina prin marcajul de sfarsit
de linie.
Exemplu
seceta.in seceta.out Explicat ie
3 624 Costul minim este [6.24264 * 100]=624
1 4 prin legarea perechilor:
3 3 Gradini Fantani
4 7 1 4 2 3
2 3 3 3 3 1
2 5 4 7 2 5
3 1
Timp maxim de execut ie/test: 1 sec sub Windows si 0.5 sec sub Linux.
340 CAPITOLUL 14. ONI 2005 CLASA A IX-A
14.3.1 Indicat ii de rezolvare - descriere solut ie *
Solut ia ocial a, lect. Ovidiu Domsa
Numarul mic al punctelor permite generarea tuturor posibilitat ilor de a conecta
o gr adina cu o fant ana neconectata la un moment dat.
Pentru ecare astfel de combinat ie g asit a se calculeaz a suma distant elor
(Gi, Fj), n linie dreapta, folosind formula distant ei dintre dou a puncte n plan,
studiat a la geometrie. (d(A(x, y), B(z, t) =
_
(x z)
2
+ (y t)
2
).
Acest a solut ie implementata corect asigura 60 70 de puncte.
Pentru a obt ine punctajul maxim se tine cont de urmatoarele aspecte:
1. Se construieste n prealabil matricea distant elor d(i, j) cu semnicat ia
distant ei dintre gr adina i si fant ana j. Aceasta va reduce timpul de calcul la
variantele cu peste 9 perechi.
2. Pentru a elimina cazuri care nu pot constitui solut ii optime se foloseste
proprietatea patrulaterului ca suma a doua laturi opuse (condit ie care asigura
unicitatea conectarii unei singure fant ani la o singur a gr adina) este mai mica decat
suma diagonalelor. De aceea nu se vor lua n considerare acele segmente care se
intersecteaza. Condit ia de intersect ie a dou a segmente care au capetele n punctele
de coordonate A(a1, a2), B(b1, b2), C(c1, c2), D(d1, d2) este ca luand segmentul
AB, punctele C si D s a se ae de aceeasi parte a segmentului AB si respectiv
pentru segmentul CD, punctele A si B s a se ae de aceeasi parte (se nlocuieste
n ecuat ia dreptei ce trece prin dou a puncte, studiat a n clasa a 9-a).
Observat ie: Pentru cei interesat i, problema are solut ie si la un nivel superior,
folosind algoritmul de determinare a unui ux maxim de cost minim.
14.3.2 Rezolvare detaliata
14.3.3 Codul sursa *
Variant a cu determinarea intesect iei segmentelor.
import java.io.*; // cu determinarea intesectiei segmentelor
class Seceta1 // Java este "mai incet" decat Pascal si C/C++
{ // test 9 ==> 2.23 sec
static int nv=0;
static int n;
static int[] xg, yg, xf, yf, t, c;
static int[] a; // permutare: a[i]=fantana asociata gradinii i
static double costMin=200*1.42*12*100;
static double[][] d;
static PrintWriter out;
14.3. SECETA 341
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
long t1,t2;
t1=System.currentTimeMillis();
citire();
rezolvare();
afisare();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1)+" ms");
}
static void citire() throws IOException
{
int k;
st=new StreamTokenizer(new BufferedReader(new FileReader("seceta.in")));
st.nextToken(); n=(int)st.nval;
xg=new int[n+1];
yg=new int[n+1];
xf=new int[n+1];
yf=new int[n+1];
a=new int[n+1];
d=new double[n+1][n+1];
for(k=1;k<=n;k++)
{
st.nextToken(); xg[k]=(int)st.nval;
st.nextToken(); yg[k]=(int)st.nval;
}
for(k=1;k<=n;k++)
{
st.nextToken(); xf[k]=(int)st.nval;
st.nextToken(); yf[k]=(int)st.nval;
}
}
static void rezolvare() throws IOException
{
int i,j;
int s;
for(i=1;i<=n;i++) // gradina i
for(j=1;j<=n;j++) // fantana j
342 CAPITOLUL 14. ONI 2005 CLASA A IX-A
{
s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);
d[i][j]=Math.sqrt(s);
}
f(1); // generez permutari
}
static void f(int k)
{
boolean ok;
int i,j;
for(i=1;i<=n;i++)
{
ok=true; // k=1 ==> nu am in stanga ... for nu se executa !
for(j=1;j<k;j++) if(i==a[j]) {ok=false; break;}
if(!ok) continue;
for(j=1;j<k;j++)
if(seIntersecteaza(xg[k],yg[k],xf[i], yf[i],
xg[j],yg[j],xf[a[j]],yf[a[j]]))
{
ok=false;
break;
}
if(!ok) continue;
a[k]=i;
if(k<n) f(k+1); else verificCostul();
}
}
static void verificCostul()
{
int i;
double s=0;
for(i=1;i<=n;i++) s=s+d[i][a[i]];
if(s<costMin) costMin=s;
}
// de ce parte a dreptei [(xa,ya);(xb,yb)] se afla (xp,yp)
static int s(int xp,int yp,int xa,int ya,int xb,int yb)
{
double s=(double)yp*(xb-xa)-xp*(yb-ya)+xa*yb-xb*ya;
if(s<-0.001) return -1; // in zona "negativa"
else if(s>0.001) return 1; // in zona "pozitiva"
else return 0; // pe dreapta suport
14.3. SECETA 343
}
// testeaza daca segmentul[P1,P1] se intersecteaza cu [P3,P4]
static boolean seIntersecteaza(int x1, int y1, int x2, int y2,
int x3, int y3, int x4, int y4)
{
double x,y;
if((x1==x2)&&(x3==x4)) // ambele segmente verticale
if(x1!=x3) return false;
else if(intre(y1,y3,y4)||intre(y2,y3,y4)) return true;
else return false;
if((y1==y2)&&(y3==y4)) // ambele segmente orizontale
if(y1!=y3) return false;
else if(intre(x1,x3,x4)||intre(x2,x3,x4)) return true;
else return false;
if((y2-y1)*(x4-x3)==(y4-y3)*(x2-x1)) // au aceeasi panta (oblica)
if((x2-x1)*(y3-y1)==(y2-y1)*(x3-x1)) // au aceeasi dreapta suport
if(intre(x1,x3,x4)||intre(x2,x3,x4)) return true;
else return false;
else return false;// nu au aceeasi dreapta suport
else // nu au aceeasi panta (macar unul este oblic)
{
x=(double)((x4-x3)*(x2-x1)*(y3-y1)-
x3*(y4-y3)*(x2-x1)+
x1*(y2-y1)*(x4-x3))/
((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
if(x2!=x1) y=y1+(y2-y1)*(x-x1)/(x2-x1); else y=y3+(y4-y3)*(x-x3)/(x4-x3);
if(intre(x,x1,x2)&&intre(y,y1,y2)&&intre(x,x3,x4)&&intre(y,y3,y4))
return true; else return false;
}
}
static boolean intre(int c, int a, int b) // c este in [a,b] ?
{
int aux;
if(a>b) {aux=a; a=b; b=aux;}
if((a<=c)&&(c<=b)) return true; else return false;
}
static boolean intre(double c, int a, int b) // c este in [a,b] ?
{
int aux;
344 CAPITOLUL 14. ONI 2005 CLASA A IX-A
if(a>b) {aux=a; a=b; b=aux;}
if((a<=c)&&(c<=b)) return true; else return false;
}
static void afisare() throws IOException
{
int k;
out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));
out.println((int)(costMin*100));
out.close();
}
}
Variant a cu cu determinarea pozitiei punctelor in semiplane si mesaje pentru
depanare.
import java.io.*; // cu determinarea pozitiei punctelor in semiplane
class Seceta2 // cu mesaje pentru depanare !
{
static int nv=0;
static int n;
static int[] xg, yg, xf, yf, t, c;
static int[] a; // permutare: a[i]=fantana asociata gradinii i
static double costMin=200*1.42*12*100;
static double[][] d;
static PrintWriter out;
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
long t1,t2;
t1=System.currentTimeMillis();
citire();
rezolvare();
afisare();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1)+" ms");
}
static void citire() throws IOException
{
int k;
st=new StreamTokenizer(new BufferedReader(new FileReader("seceta.in")));
st.nextToken(); n=(int)st.nval;
xg=new int[n+1];
14.3. SECETA 345
yg=new int[n+1];
xf=new int[n+1];
yf=new int[n+1];
a=new int[n+1];
d=new double[n+1][n+1];
for(k=1;k<=n;k++)
{
st.nextToken(); xg[k]=(int)st.nval;
st.nextToken(); yg[k]=(int)st.nval;
}
for(k=1;k<=n;k++)
{
st.nextToken(); xf[k]=(int)st.nval;
st.nextToken(); yf[k]=(int)st.nval;
}
}
static void rezolvare() throws IOException
{
int i,j;
int s;
for(i=1;i<=n;i++) // gradina i
for(j=1;j<=n;j++) // fantana j
{
s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);
d[i][j]=Math.sqrt(s);
}
f(1); // generez permutari
}
static void f(int k)
{
boolean ok;
int i,j;
for(i=1;i<=n;i++)
{
ok=true; // k=1 ==> nu am in stanga ... for nu se executa !
for(j=1;j<k;j++) if(i==a[j]) {ok=false; break;}
if(!ok) continue;
for(j=1;j<k;j++)
if((s(xg[k],yg[k],xg[j],yg[j],xf[a[j]],yf[a[j]])*
s(xf[i],yf[i],xg[j],yg[j],xf[a[j]],yf[a[j]])<0)&&
346 CAPITOLUL 14. ONI 2005 CLASA A IX-A
(s(xg[j], yg[j], xg[k],yg[k],xf[i],yf[i])*
s(xf[a[j]],yf[a[j]],xg[k],yg[k],xf[i],yf[i])<0))
{
afisv(k-1);// pe pozitia k(gradina) vreau sa pun i(fantana)
System.out.print(i+" ");// pe pozitia j(gradina) e pus a[j](fantana)
System.out.print(k+""+i+" "+j+""+a[j]);
System.out.print(" ("+xg[k]+","+yg[k]+") "+" ("+xf[i]+","+yf[i]+") ");
System.out.println(" ("+xg[j]+","+yg[j]+") "+" ("+xf[a[j]]+","+yf[a[j]]+") ");
ok=false;
break;
}
if(!ok) continue;
a[k]=i;
if(k<n) f(k+1); else verificCostul();
}
}
static void verificCostul()
{
int i;
double s=0;
for(i=1;i<=n;i++) s=s+d[i][a[i]];
if(s<costMin) costMin=s;
afisv(n); System.out.println(" "+s+" "+costMin+" "+(++nv));
}
static void afisv(int nn)
{
int i;
for(i=1;i<=nn;i++) System.out.print(a[i]);
}
// de ce parte a dreptei [(xa,ya);(xb,yb)] se afla (xp,yp)
static int s(int xp,int yp,int xa,int ya,int xb,int yb)
{
double s=(double)yp*(xb-xa)-xp*(yb-ya)+xa*yb-xb*ya;
if(s<-0.001) return -1; // in zona "negativa"
else if(s>0.001) return 1; // in zona "pozitiva"
else return 0; // pe dreapta suport
}
static void afisare() throws IOException
14.3. SECETA 347
{
int k;
out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));
out.println((int)(costMin*100));
out.close();
}
}
Variant a cu cu determinarea pozitiei punctelor in semiplane, far amesaje pen-
tru depanare.
import java.io.*; // cu determinarea pozitiei punctelor in semiplane
class Seceta3 // Java este "mai incet" decat Pascal si C/C++
{ // test 9 ==> 2.18 sec
static int n;
static int[] xg, yg, xf, yf, t, c;
static int[] a; // permutare: a[i]=fantana asociata gradinii i
static double costMin=200*1.42*12*100;
static double[][] d;
static PrintWriter out;
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
long t1,t2;
t1=System.currentTimeMillis();
citire();
rezolvare();
afisare();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1)+" ms");
}
static void citire() throws IOException
{
int k;
st=new StreamTokenizer(new BufferedReader(
new FileReader("seceta.in")));
st.nextToken(); n=(int)st.nval;
xg=new int[n+1];
yg=new int[n+1];
xf=new int[n+1];
yf=new int[n+1];
a=new int[n+1];
d=new double[n+1][n+1];
348 CAPITOLUL 14. ONI 2005 CLASA A IX-A
for(k=1;k<=n;k++)
{
st.nextToken(); xg[k]=(int)st.nval;
st.nextToken(); yg[k]=(int)st.nval;
}
for(k=1;k<=n;k++)
{
st.nextToken(); xf[k]=(int)st.nval;
st.nextToken(); yf[k]=(int)st.nval;
}
}
static void rezolvare() throws IOException
{
int i,j;
int s;
for(i=1;i<=n;i++) // gradina i
for(j=1;j<=n;j++) // fantana j
{
s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);
d[i][j]=Math.sqrt(s);
}
f(1); // generez permutari
}
static void f(int k)
{
boolean ok;
int i,j;
for(i=1;i<=n;i++)
{
ok=true; // k=1 ==> nu am in stanga ... for nu se executa !
for(j=1;j<k;j++) if(i==a[j]) {ok=false; break;}
if(!ok) continue;
for(j=1;j<k;j++)
if((s(xg[k], yg[k], xg[j],yg[j],xf[a[j]],yf[a[j]])*
s(xf[i], yf[i], xg[j],yg[j],xf[a[j]],yf[a[j]])<0)&&
(s(xg[j], yg[j], xg[k],yg[k],xf[i], yf[i])*
s(xf[a[j]],yf[a[j]],xg[k],yg[k],xf[i], yf[i])<0))
{
ok=false;
break;
}
14.3. SECETA 349
if(!ok) continue;
a[k]=i;
if(k<n) f(k+1); else verificCostul();
}
}
static void verificCostul()
{
int i;
double s=0;
for(i=1;i<=n;i++) s=s+d[i][a[i]];
if(s<costMin) costMin=s;
}
//de ce parte a dreptei [(xa,ya);(xb,yb)] se afla (xp,yp)
static int s(int xp,int yp,int xa,int ya,int xb,int yb)
{
double s=(double)yp*(xb-xa)-xp*(yb-ya)+xa*yb-xb*ya;
if(s<-0.001) return -1; // in zona "negativa"
else if(s>0.001) return 1; // in zona "pozitiva"
else return 0; // pe dreapta suport
}
static void afisare() throws IOException
{
int k;
out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));
out.println((int)(costMin*100));
out.close();
}
}
Varianta 4:
import java.io.*; // gresit (!) dar ... obtine 100p ... !!!
class Seceta4 // test 9 : 2.18 sec --> 0.04 sec
{
static int n;
static int[] xg, yg, xf, yf, t, c;
static int[] a; // permutare: a[i]=fantana asociata gradinii i
static double costMin=200*1.42*12*100;
static double[][] d;
static boolean[] epus=new boolean[13];
static PrintWriter out;
350 CAPITOLUL 14. ONI 2005 CLASA A IX-A
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
long t1,t2;
t1=System.currentTimeMillis();
citire();
rezolvare();
afisare();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1)+" ms");
}// main(...)
static void citire() throws IOException
{
int k;
st=new StreamTokenizer(new BufferedReader(new FileReader("seceta.in")));
st.nextToken(); n=(int)st.nval;
xg=new int[n+1];
yg=new int[n+1];
xf=new int[n+1];
yf=new int[n+1];
a=new int[n+1];
d=new double[n+1][n+1];
for(k=1;k<=n;k++)
{
st.nextToken(); xg[k]=(int)st.nval;
st.nextToken(); yg[k]=(int)st.nval;
}
for(k=1;k<=n;k++)
{
st.nextToken(); xf[k]=(int)st.nval;
st.nextToken(); yf[k]=(int)st.nval;
}
}// citire(...)
static void rezolvare() throws IOException
{
int i,j;
int s;
14.3. SECETA 351
for(i=1;i<=n;i++) // gradina i
for(j=1;j<=n;j++) // fantana j
{
s=(xg[i]-xf[j])*(xg[i]-xf[j])+(yg[i]-yf[j])*(yg[i]-yf[j]);
d[i][j]=Math.sqrt(s);
}
f(1); // generez permutari
}// rezolvare(...)
static void f(int k)
{
int i,j;
boolean seIntersecteaza;
for(i=1;i<=n;i++)
{
if(epus[i]) continue;
seIntersecteaza=false;
for(j=1;j<=k-1;j++)
if(d[k][i]+d[j][a[j]]>d[j][i]+d[k][a[j]])
{
seIntersecteaza=true;
break;
}
if(seIntersecteaza) continue;
a[k]=i;
epus[i]=true;
if(k<n) f(k+1); else verificCostul();
epus[i]=false;
}// for i
}// f(...)
static void verificCostul()
{
int i;
double s=0;
for(i=1;i<=n;i++) s=s+d[i][a[i]];
if(s<costMin) costMin=s;
}// verificCostul(...)
static void afisare() throws IOException
{
352 CAPITOLUL 14. ONI 2005 CLASA A IX-A
int k;
out=new PrintWriter(new BufferedWriter(new FileWriter("seceta.out")));
out.println((int)(costMin*100));
out.close();
}// afisare(...)
}// class
14.4 Biblos
Maria si Adrian Nit a
Din dorint a de a realiza un fond de carte cat mai voluminos, ocialitat ile
orasului Galat i, au modernizat pentru nceput, o sala pentru depozitarea c art ilor
si l-au numit pe Biblos coordonatorul acestei biblioteci.
Achizit ionarea de carte s-a realizat n mai multe etape.
De ecare data cart ile achizit ionate au fost depozitate pe cate un stativ con-
struit special de Biblos.
Pentru a avea spat iu de depozitare Biblos a construit mai multe stative decat
i-ar fost necesare, unele put and r amane far a cart i.
Dup a mai multe etape de achizit ionare, Biblos a constatat ca spat iul alocat
bibliotecii este prea mic.
Primind un alt spat iu mai ncapator, muta primul stativ cu toate cart ile
cont inute de acesta si se opreste deoarece si doreste s a mute acele stative care nu
sunt asezate unul l anga celalalt si care fac ca fondul de carte din noua sala s a e
cat mai mare posibil.
Cerint a
Scriet i un program care, cunosc and num arul stativelor, precum si num arul
de volume de carte de pe ecare stativ, determin a care este num arul maxim de
volume care pot mutate n noua sala, stiind ca primul stativ a fost deja mutat
iar celelalte se aleg astfel ncat s a nu e asezate unul l anga celalalt. Daca exista
stative care nu au cart i acestea nu vor mutate n a doua sala.
Date de intrare
Fisierul de intrare biblos.in cont ine
pe prima linie o valoare n, num ar natural cu semnicat ia num arul de stative,
pe a doua linie n numere naturale, x
1
, x
2
, ..., x
n
separate prin cate un
spat iu cu semnicat ia
x
i
= num arul de volume de carte existente pe ecare stativ.
Date de iesire
Fisierul de iesire biblos.out va cont ine o singur a linie unde se aa un num ar
natural cu semnicat ia: num arul maxim de volume ce au fost transferate.
Restrict ii si precizari
1 n 30000
14.4. BIBLOS 353
0 x
i
32767, unde i = 1, ..., n iar x
i
reprezint a num arul de cart i de pe
stativul i.
Pentru 70% dintre teste n 1000
Fiecare linie din sierul de intrare si din sierul de iesire se termin a cu
marcaj de sfarsit de linie.
Exemple
biblos.in biblos.out
7 16
1 3 6 2 5 8 4
Explicat ie: Suma maxima se obt ine din mutarea stativelor 1 (obligatoriu), 3,
5, 7 (nu pot stative al aturate)
biblos.in biblos.out
15 836
3 1 84 9 89 55 135 49 176 238 69 112 28 175 142
Explicat ie: Suma maxima obt inuta din mutarea stativelor 1, 3, 5, 7, 10, 12,
14
biblos.in biblos.out
8 32
7 1 4 12 9 9 12 4
Explicat ie: Suma maxima obt inuta din mutarea stativelor 1, 3, 5, 7, sau din
mutarea stativelor 1, 4, 6, 8.
Timp maxim de execut ie/test: 0.5 sec sub Windows si 0.1 sec sub Linux
14.4.1 Indicat ii de rezolvare - descriere solut ie *
Solut ia ocial a, Maria si Adrian Nit a
Problema cere determinarea unei sume maxime format a din numerele citite,
astfel ncat s a se aleag a doar valori care nu sunt pe pozit ii consecutive.
Structurile folosite sunt:
carti(1), carti(2), ... carti(n)
unde carti(i) = num arul de volume existente pe stativul i (i = 1, ..., n).
cmax(1), cmax(2), ..., cmax(n)
unde cmax(i) = num arul maxim de volume ce pot transferate utiliz and
cart ile existente pe stativele de la 1 la i 2, astfel ncat s a e selectat si raftul i.
Primul stativ indntotdeauna transferat atunci realizarea lui cmax se poate
face astfel:
cmax(1) = carti(1);
354 CAPITOLUL 14. ONI 2005 CLASA A IX-A
Pentru toate celelalte valori cmax(i), se observa ca se poate folosi formula:
cmax(i) = carti(i) +maxim{cmax(k) unde k = 1, ..., i 2}
Prin alegerea maximului dintre valorile lui cmax, se obt ine rezultatul cerut.
Pentru optimizare, se poate face observat ia ca dintre valorile lui cmax, in-
tereseaza doar cele de pe pozit iile i 3 si i 2, deci:
dac a cmax(i 2) > cmax(i 3)
atunci cmax(i) = cmax(i 2) +carti(i)
altfel cmax(i) = cmax(i 3) +carti(i)/
14.4.2 Rezolvare detaliata
14.4.3 Codul sursa *
Variant a pentru depanare.
import java.io.*;
class Biblos1
{
static int n;
static int[] x;
static int[] smax;
static int[] p; // predecesor, pentru depanare
public static void main(String []args) throws IOException
{
long t1,t2;
t1=System.currentTimeMillis();
int i,j,max,jmax,ji;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("biblos.in")));
PrintWriter out = new PrintWriter (
new BufferedWriter( new FileWriter("biblos.out")));
st.nextToken();n=(int)st.nval;
x=new int[n+1];
smax=new int[n+1];
p=new int[n+1];
for(i=1;i<=n;i++) { st.nextToken(); x[i]=(int)st.nval;}
14.4. BIBLOS 355
smax[1]=x[1];
for(i=2;i<=n;i++)
{
max=0; jmax=0;
if(i==2) ji=0; else ji=i-3;
for(j=ji;j<=i-2;j++)
if(smax[j]>=max) { max=smax[j]; jmax=j; }
if(max!=0) { smax[i]=max+x[i]; p[i]=jmax;} else {smax[i]=0; p[i]=0;}
}
if(smax[n]>smax[n-1]) {max=smax[n]; jmax=n;}
else {max=smax[n-1]; jmax=n-1;}
out.println(max);
out.close();
t2=System.currentTimeMillis();
drum(jmax);
System.out.println("Timp = "+(t2-t1)+" ms");
}//main
static void drum(int j)
{
if(p[j]!=0) drum(p[j]);
System.out.println(j+" "+x[j]+" "+smax[j]);
}
}//class
Variant a cu vectori.
import java.io.*;
class Biblos2
{
static int n;
static int[] x;
static int[] smax;
public static void main(String []args) throws IOException
{
int i,j,max,jmax,ji;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("biblos.in")));
PrintWriter out = new PrintWriter (
new BufferedWriter( new FileWriter("biblos.out")));
356 CAPITOLUL 14. ONI 2005 CLASA A IX-A
st.nextToken();n=(int)st.nval;
x=new int[n+1];
smax=new int[n+1];
for(i=1;i<=n;i++) { st.nextToken(); x[i]=(int)st.nval;}
smax[1]=x[1];
for(i=2;i<=n;i++)
{
max=0; jmax=0;
if(i==2) ji=0; else ji=i-3;
for(j=ji;j<=i-2;j++)
if(smax[j]>=max) { max=smax[j]; jmax=j; }
if(max!=0) smax[i]=max+x[i]; else smax[i]=0;
}
if(smax[n]>smax[n-1]) max=smax[n]; else max=smax[n-1];
out.println(max);
out.close();
}//main
}//class
Variant a far a vectori (optimizat spat iul de memorie folosit).
import java.io.*; // s-a renuntat la vectorii x si smax
class Biblos3
{
static int n;
static int xi;
static int si,si1,si2,si3;
public static void main(String []args) throws IOException
{
int i,j,max,jmax,ji;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("biblos.in")));
PrintWriter out = new PrintWriter (
new BufferedWriter( new FileWriter("biblos.out")));
st.nextToken();n=(int)st.nval;
st.nextToken(); xi=(int)st.nval;
si3=0;
si2=xi;
si1=0;
st.nextToken(); xi=(int)st.nval; // citesc x[2] si il neglijez !
14.5. JOC 357
for(i=3;i<=n;i++)
{
st.nextToken(); xi=(int)st.nval;
if(si2>si3) si=si2+xi; else si=si3+xi;
si3=si2;
si2=si1;
si1=si;
}
if(si1>si2) out.println(si1); else out.println(si2);
out.close();
}//main
}//class
14.5 Joc
Cristina Luca
Pe o tabl a patrata de dimensiune n n se deseneaza o secvent a de
triunghiuri dreptunghic isoscele.
Fiecare triunghi are v arfurile numerotate cu 1, 2 si 3 (2 corespunde unghiului
drept iar ordinea 1, 2, 3 a v arfurilor este n sens invers acelor de ceasornic - vezi
gura). Triunghiurile au catetele paralele cu marginile tablei.
Primul triunghi, av and lungimea catetei Lg, are v arful 1 pe linia L si coloana
C si este orientat ca n gura.
3
a
a a
a a a
1 a a a a 2
Jocul const an alipirea cate unui nou triunghi la unul din v arfurile 2 sau 3 ale
triunghiului curent. Daca se al atur a colt ului 2, noul triunghi se aseaza cu v arful 1
n prelungirea laturii [1, 2] a triunghiului curent, iar dac a se al atur a colt ului 3 se
aseaza cu v arful 1 n prelungirea laturii [2, 3].
Init ial noul triunghi este orientat ca si cel anterior. El se poate plasa pe tabl a
dac a nu sunt depasite marginile acesteia sau nu se suprapune peste un alt triunghi.
, 11 =
,...,35 =
);
un test va punctat doar dac a toate cele 5 rezultate cerute sunt corecte.
Exemplu
.in .out Explicat ie
5 10 2 5! = 120, n baza 10, deci ultima cifra nenula este 2
7 10 4 7! = 5040, n baza 10, deci ultima cifra nenula este 4
7 20 C 7! = CC0, n baza 20, deci ultima cifra nenula este C
8 16 8 8! = 9D80, n baza 16, deci ultima cifra nenula este 8
9 8 6 9! = 1304600, n baza 8, deci ultima cifra nenula este 6
Timp maxim de execut ie/test: 1 secunda (Windows), 0.3 secunde (Linux)
15.1.1 Indicat ii de rezolvare - descriere solut ie *
Solut ia comisiei
Se descompune mai nt ai B n produs de factori primi. Retinem n d[i][0]
factorul prim cu numarul de ordine i si n d[i][1] puterea la care apare acesta n
descompunerea lui B.
Apoi se parcurg numerele de la 1 la N si din ecare dintre acestea se elimina
tot i factorii primi ai lui B, ret inut i n d[i][0]. Se pastreaza totodatan d[i][2] puterea
la care ar aparut acestia n descompunerea lui N!. Odat a cu eliminarea factorilor
primi ai lui B din N!, se calculeaz a si restul lampart irea cu B al produsului (notat
p).
Se calculeaz a apoi num arul de zerouri consecutive care se vor aa la sfarsitul
lui N!, reprezentat n baza B: minimul rapoartelor dintre d[i][2] si d[i][1], notat
min. Se face diferenta ntre d[i][2] si min d[i][1], adica num arul de elemente
d[i][0] care mai trebuie nmult ite cu p si se fac aceste nmult iri moduloB. Acesta
este rezultatul cautat.
15.1. FACTORIAL 375
15.1.2 Rezolvare detaliata
15.1.3 Codul sursa *
import java.io.*;
class Factorial
{
static int n,b,m,p;
static int[] fb=new int[10];
static int[] eb=new int[10];
static int[] en=new int[10];
static void descf(int nr)
{
int d;
m=0;
d=2;
if(nr%d==0) {m++; fb[m]=d; eb[m]=0;}
while(nr%d==0) {eb[m]++; nr/=d; }
d=3;
while(d*d<=nr)
{
if(nr%d==0) {m++; fb[m]=d; eb[m]=0;}
while(nr%d==0) {eb[m]++;nr/=d; }
d=d+2;
}
if(nr!=1) {m++; fb[m]=nr; eb[m]=1;}
}//descf(...)
static void calcul()
{
int i,ii,j,min;
descf(b);
p=1;
for(j=1;j<=m;j++) en[j]=0;
for(i=2;i<=n;i++) // n!
{
ii=i;
for(j=1;j<=m;j++) while(ii%fb[j]==0) { en[j]++; ii/=fb[j]; }
376 CAPITOLUL 15. ONI 2006 CLASA A IX-A
p=(p*(ii%b))%b;
}
min=en[1]/eb[1];
for(j=2;j<=m;j++) if(en[j]/eb[j]<min) min=en[j]/eb[j];
for(j=1;j<=m;j++) en[j]=en[j]-min*eb[j];
for(j=1;j<=m;j++) for(i=1;i<=en[j];i++) p=(p*(fb[j]%b))%b;
}// calcul()
public static void main(String[] args) throws IOException
{
int k;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("fact.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("fact.out")));
for(k=1;k<=5;k++)
{
st.nextToken(); n=(int)st.nval;
st.nextToken(); b=(int)st.nval;
calcul();
if(p<=9) out.println(p); else out.println((char)(p-10+A));
}
out.close();
}// main(...)
}// class
15.2 Limbaj
autor Domsa Ovidiu
Universitatea 1 Decembrie 1918 Alba Iulia
Denim un limbaj de programare, cu instruct iuni de atribuire si de decizie.
Sintaxa instruct iunilor este:
Instruct iunea de atribuire
variabila=variabila
Instruct iunea de decizie
if
semn variabila variabila
{da
instruct iuni }
15.2. LIMBAJ 377
{ nu
instruct iuni }
,
>
sau
=
.
Liniile instruct iunilor nu cont in spat ii.
Instruct iunile din { } pot lipsi.
Cerint a
Daca se dau valorile init iale ale tuturor variabilelor (de la a la z), n ordine
alfabetica ncepand cu a, se cer valorile tuturor variabilelor de la a la z, dupa
execut ia secvent ei de program.
Date de intrare
Fisier de intrare: limbaj.in
Linia 1: V
a
V
b
... V
z
- Valorile init iale ale variabilelor, de la a la z, separate
prin cate un spat iu.
Linia 2: linie de program - Urm atoarele linii, pana la sfarsitul sierului cont in
linii de program,
Linia 3: linie de program cu instruct iuni corecte din punct de vedere sintac-
tic.
....
Date de iesire
Fisier de iesire: limbaj.out
Linia 1: V
a
V
b
... V
z
- sirul valorilor variabilelor, de la a la z, n ordine
alfabetica, pe un r and, separate prin cate un spat iu.
Restrict ii si precizari
30000 < a, b, .., z < 30000
Numarul liniilor de program este mai mic decat 10000
Limbajul este case sensitive (se folosesc doar litere mici de la a la z).
Exemplu
378 CAPITOLUL 15. ONI 2006 CLASA A IX-A
limbaj.in
1 3 5 7 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
if
=ab
nu
if
<ab
da
b=d
f=d
limbaj.out
1 7 5 7 4 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Timp maxim de execut ie/test: 0.5 secunde (Windows), 0.1 secunde
(Linux)
15.2.1 Indicat ii de rezolvare - descriere solut ie *
Solut ia comisiei
Solut ia problemei const a n parcurgerea liniara a instruct iunilor linie cu linie
si pastrarea valorilor logice ale condit iilor si respectiv a ramurilor da si nuntr-un
sir.
Semnicat ia pozit iei din sir este nivelul de imbricare la care ne aam. Practic
parcurgem, far a a evalua, acele instruct iuni care nu apart in nivelului si ramurii pe
care ne aam.
In acest sens vom evalua instruct iunile de atribuire doar cele care ndeplinesc
condit iile de a se aa pe nivelul corespunzator si pentru care valorile condit iilor si
respectiv a ramurilor sunt n acealsi timp adevarate.
15.2.2 Rezolvare detaliata
15.2.3 Codul sursa *
Variant a cu mesaje:
import java.io.*; // test 25 g,h= gresit la ei!!!
class LimbajMesaje // test 26 ==> liniile 321 si 400 si 479= "fiif" ... ???
{ // test 28 ==> multe linii cu "fiif" ... ???
static int[] x=new int[26];
15.2. LIMBAJ 379
static char[] a=new char[4];
static String s;
static BufferedReader brin;
static StreamTokenizer stin;
static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
static void afisx()
{
int i;
for(i=0;i<26;i++) System.out.print(x[i]+" ");
System.out.println();
}// afisx()
static void afisa()
{
int i;
for(i=0;i<a.length;i++) System.out.print(a[i]+" ");
System.out.println();
}// afisa()
static boolean esteif()
{
if((a[0]==i)&&(a[1]==f)) return true; else return false;
} // esteif()
static boolean estefi()
{
if((a[0]==f)&&(a[1]==i)) return true; else return false;
}// estefi()
static boolean esteda()
{
if((a[0]==d)&&(a[1]==a)) return true; else return false;
}// esteda()
static boolean estenu()
{
if((a[0]==n)&&(a[1]==u)) return true; else return false;
}// estenu()
static void blocda(boolean ok) throws IOException
{
System.out.println(" --> blocDA: "+s+" ok="+ok); //br.readLine();
380 CAPITOLUL 15. ONI 2006 CLASA A IX-A
bloc(ok);
System.out.println(" <-- blocDA: "+s+" ok="+ok); //br.readLine();
}// blocda(...)
static void blocnu(boolean ok) throws IOException
{
System.out.println(" --> blocNU: "+s+" ok="+ok); //br.readLine();
bloc(ok);
System.out.println(" <-- blocNU: "+s+" ok="+ok); //br.readLine();
}// blocnu(...)
static void blocif(boolean ok) throws IOException
{
System.out.println(" --> blocif: "+s+" ok="+ok); //br.readLine();
boolean oke=false;
// urmeaza expresia logica (conditia din IF)
s=brin.readLine(); a=s.toCharArray();
System.out.println("evaluare expresie: "+s+" --> oke = "+oke+" ok="+ok);
//br.readLine();
afisx();
if(a[0]=== && x[a[1]-a] == x[a[2]-a]) oke=true; else
if(a[0]==< && x[a[1]-a] < x[a[2]-a]) oke=true; else
if(a[0]==> && x[a[1]-a] > x[a[2]-a]) oke=true;
// urmeaza "DA" sau "NU"
s=brin.readLine(); a=s.toCharArray();
System.out.println(" ? bloc DA ? s= "+s);
if(esteda())
{
s=brin.readLine(); a=s.toCharArray();
blocda(ok && oke);
}
System.out.println(" ? bloc NU ? s= "+s);
if(estenu())
{
s=brin.readLine(); a=s.toCharArray();
blocnu(ok && !oke);
}
s=brin.readLine(); if(s!=null) a=s.toCharArray();
15.2. LIMBAJ 381
System.out.println(" <-- blocif: "+s+" ok="+ok); //br.readLine();
}// blocif(...)
static void blocatr(boolean ok) throws IOException
{
System.out.println(" --> blocatr: "+s+" ok="+ok); //br.readLine();
if(ok) x[a[0]-a]=x[a[2]-a];
// mai sunt si alte atribuiri consecutive ...
s=brin.readLine(); if(s!=null) a=s.toCharArray();
while((s!=null)&&(a[1]===))
{
System.out.println(" "+s+" ok="+ok); //br.readLine();
if(ok) x[a[0]-a]=x[a[2]-a];
s=brin.readLine(); if(s!=null) a=s.toCharArray();
}
System.out.println(" <-- blocatr: "+s); //br.readLine();
}// blocatr(...)
static void blocelem(boolean ok) throws IOException
{
if(estefi()||esteda()||estenu()) return;
System.out.println(" --> blocelem: "+s); //br.readLine();
if(a[1]===) blocatr(ok);
if(esteif()) blocif(ok);
System.out.println(" <-- blocelem: "+s); //br.readLine();
}// blocelem(...)
static void bloc(boolean ok) throws IOException // blocElementar + blocElementar +...
{
System.out.println("--> bloc: "+s); //br.readLine();
while(s!=null&&!estefi()&&!esteda()&&!estenu())
{
blocelem(ok);
}
System.out.println("<-- bloc: "+s); //br.readLine();
}// bloc(...)
public static void main(String[] args) throws IOException
{
int k;
brin=new BufferedReader(new FileReader("limbaj.in"));
382 CAPITOLUL 15. ONI 2006 CLASA A IX-A
stin=new StreamTokenizer(brin);
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("limbaj.out")));
int i;
for(i=0;i<26;i++) { stin.nextToken(); x[i]=(int)stin.nval; }
brin.readLine();
afisx();
s=brin.readLine();
if(s!=null) a=s.toCharArray();
bloc(true);
for(i=0;i<26;i++) out.print(x[i]+" ");
out.println();
out.close();
}// main(...)
}// class
Variant a far a mesaje:
import java.io.*; // test 25 g,h= gresit la ei!!!
class Limbaj // test 26 ==> liniile 321 si 400 si 479= "fiif" ... ???
{ // test 28 ==> multe linii cu "fiif" ...
static int[] x=new int[26];
static char[] a=new char[4];
static String s;
static BufferedReader brin;
static StreamTokenizer stin;
static boolean esteif()
{
if((a[0]==i)&&(a[1]==f)) return true; else return false;
}// esteif()
static boolean estefi()
{
if((a[0]==f)&&(a[1]==i)) return true; else return false;
}// esteif()
static boolean esteda()
{
15.2. LIMBAJ 383
if((a[0]==d)&&(a[1]==a)) return true; else return false;
}// esteda()
static boolean estenu()
{
if((a[0]==n)&&(a[1]==u)) return true; else return false;
}// estenu()
static void blocif(boolean ok) throws IOException
{
boolean oke=false;
// urmeaza expresia logica (conditia din IF)
s=brin.readLine(); a=s.toCharArray();
if(a[0]=== && x[a[1]-a] == x[a[2]-a]) oke=true; else
if(a[0]==< && x[a[1]-a] < x[a[2]-a]) oke=true; else
if(a[0]==> && x[a[1]-a] > x[a[2]-a]) oke=true;
// urmeaza "DA" sau "NU"
s=brin.readLine(); a=s.toCharArray();
if(esteda())
{
s=brin.readLine(); a=s.toCharArray();
bloc(ok && oke);
}
if(estenu())
{
s=brin.readLine(); a=s.toCharArray();
bloc(ok && !oke);
}
s=brin.readLine(); if(s!=null) a=s.toCharArray();
}// blocif(...)
static void blocatr(boolean ok) throws IOException
{
if(ok) x[a[0]-a]=x[a[2]-a];
// mai sunt si alte atribuiri consecutive ...
s=brin.readLine(); if(s!=null) a=s.toCharArray();
while((s!=null)&&(a[1]===))
384 CAPITOLUL 15. ONI 2006 CLASA A IX-A
{
if(ok) x[a[0]-a]=x[a[2]-a];
s=brin.readLine(); if(s!=null) a=s.toCharArray();
}
}// blocatr(...)
static void blocelem(boolean ok) throws IOException
{
if(estefi()||esteda()||estenu()) return;
if(a[1]===) blocatr(ok);
if(esteif()) blocif(ok);
}// blocelem(...)
static void bloc(boolean ok) throws IOException// blocElementar + blocElementar +...
{
while(s!=null&&!estefi()&&!esteda()&&!estenu()) blocelem(ok);
}// bloc(...)
public static void main(String[] args) throws IOException
{
int k;
brin=new BufferedReader(new FileReader("limbaj.in"));
stin=new StreamTokenizer(brin);
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("limbaj.out")));
int i;
for(i=0;i<26;i++) { stin.nextToken(); x[i]=(int)stin.nval; }
brin.readLine();
s=brin.readLine();
if(s!=null) a=s.toCharArray();
bloc(true);
for(i=0;i<26;i++) out.print(x[i]+" ");
out.println();
out.close();
}// main(...)
}// class
15.3. PANOURI 385
15.3 Panouri
autor G al at an Con-
stantin, ISJ Bistrita-Nasaud
Pe autostrada Soarele Estului sunt asezate de-a lungul soselei, la distant e
egale, panouri publicitare ale unor rme. Aceeasi rma, poate s a aiba mai multe
panouri publicitare si ecare panou poate s a apar a n mai multe locuri. Panourile
se identica prin numere naturale, num arul total de panouri ind N.
Firma X Corporation are panouri de T tipuri diferite. Firma a primit apro-
barea construirii unui mare complex turistic n apropierea autostr azii; de aceea,
pentru alegerea locului, este interesata si de urmatorul aspect: care este lungimea
minima de sosea, n care se pot nt alni, toate cele T tipuri de panouri publicitare
ale rmei, indiferent de ordinea acestora, si indiferent dac antre ele se mai interpun
sau nu panouri ale altor rme.
Cerint a
Cunosc and N - num arul total de panouri de la marginea autostr azii si ordinea
amplas arii lor, ca si cele T tipuri de panouri amplasate de rma, determinat i
num arul minim de intervale dintre dou a panouri ntre care rma X Corporation
si reg aseste toate panourile sale.
Date de intrare
Fisierul de intrare panouri.in are pe prima linie numerele N si T.
Pe urmatoarele N linii, sunt N numere naturale, nu neaparat diferite, cate
unul pe linie, reprezent and panourile, iar ncepand cu linia N + 2, cate unul pe
linie, cele T tipuri de panouri diferite al rmei.
Date de iesire
Fisierul de iesire panouri.out va cont ine pe prima linie un singur num ar
ntreg pozitiv L, reprezent and num arul cerut, sau 1 n caz ca nu exista solut ie.
Restrict ii si precizari
1 N 15000
1 T 1000
Toate numerele reprezent and panouri sunt numere naturale din intervalul
[1..1000].
Exemple
386 CAPITOLUL 15. ONI 2006 CLASA A IX-A
panouri.in panouri.out Explicat ie
6 2 2 Sunt N = 6 panouri : 1 2 3 5 3 1.
1 Firma are T = 2 tipuri de panouri: 5 si 1.
2
3 Cel mai scurt interval care cont ine elementele
5 5 si 1, este ntre panourile al 4 - lea
3 si al 6 -lea, si cont ine 2 intervale.
1
5
1
8 3 4 Sunt N = 8 panouri de tipurile: 5 1 3 3 5 4 2 1.
5 Firma are T = 3 tipuri de panouri: 3, 1 si 4.
1
3 Cel mai scurt interval care cont ine elementele
3 1, 3 si 4, este ntre al 2 lea si al 6-lea panou,
5 si cont ine 4 intervale.
4
2
1
3
1
4
Timp maxim de execut ie/test: 1 secunda (Windows) 0.1 secunde (Linux)
15.3.1 Indicat ii de rezolvare - descriere solut ie *
Solut ia comisiei
Reformulam problema: ind dat un sir a[1..n] si o multime B cu m elemente,
s a se gaseasca dou a pozit ii start si final, astfel ncat toate elementele mult imii
B s a e cont inute n subsecvent a a[start, ..., final], cu proprietatea ca diferent a
final start are valoare minima.
Cu alte cuvinte, s a se gaseasca subsecvent a de lungime minima a[start..final]
care cont ine toate elementele mult imii B.
Avand n vedere valorile mici pentru tipurile de panouri (1 tip 1000),
pentru operat ia de cautare n O(1) a unui element n multimea B, denim sirul
b[], cu b[i] = 1 dac a i apart ine mult imii B.
Denim de asemenea srul frecvent elor fr[], cu proprietatea ca fr[i] = x daca
i apart ine lui B si i apare de x ori n subsecvent a a[start, ..final].
Fixam start si final la valoarea 1 si increment am pozit ia final pana cand
toate elementele mult imii B se aan intervalul a[start, ..final]. Apoi incrementam
start pana la valoarea maxima la care a[start, ..final] mai cont ine nca toate
elementele mult imii B.
15.3. PANOURI 387
Intorc andu-se de la scoala n ziua n care a aat cum se face nmult irea
numerelor, Gigel a auzit la televizor urmatoarea armat ie: Pentru a face avere,
nu trebuie s a aduni bani n viat a, ci trebuie s-i nmult esti.
Toate acestea l-au pus pe g anduri, asa ca s-a hotar at s a inventeze pro-
priul sistem de codicare pentru numere reale mai mari decat 0 care s a aiba
416 CAPITOLUL 16. ONI 2007 CLASA A IX-A
urmatoarele propriet at i:
- ecare num ar va codicat sub forma unui sir de valori ntregi (pozitive
si/sau negative)
- dac a un num ar real x are codul c
x
si un num ar real y are codul c
y
, atunci
num arul real rezultat prin nmult irea lui x si y trebuie s a aiba codul obt inut prin
adunarea codurilor c x si c
y
.
- dac a un num ar real x se poate scrie ca produs de numere y
1
, y
2
, ..., y
k
,
atunci codul lui x se obt ine prin adunarea codurilor numerelor y
1
, y
2
, ..., y
k
.
Consider am un cod c
1
format din n
1
valori a
n
1
...a
1
si un cod c
2
format din
n
2
valori b
n
2
...b1, atunci codul c
3
obt inut prin adunarea codurilor c
1
si c
2
va
avea n
3
valori d
n
3
...d
1
, cu propriet at ile urmatoare:
n
3
este maximul dintre n
1
si n
2
d
i
=
_
_
a
i
+b
i
pentru i = 1, ..., min(n
1
, n
2
)
a
i
pentru i = minim(n
1
, n
2
) + 1, ..., n
1
dac a minim(n
1
, n
2
) = n
2
b
i
pentru i = minim(n
1
, n
2
) + 1, ..., n
2
dac a minim(n
1
, n
2
) = n
1
Cerint a
Dandu-se N numere reale mai mari strict decat 0, s a se scrie codicarea
acestora n sistemul inventat de Gigel.
Date de intrare
Fisierul de intrare coduri.in va cont ine:
- pe prima linie din sier se aa num arul N de numere reale
- pe urmatoarele N linii cele N numere reale, ecare pe cate o linie.
Date de iesire
Fisierul de iesire coduri.out va cont ine N linii:
- pe linia i (i ntre 1 si N) : num arul de valori folosite pentru codicarea
num arului cu indicele i din sierul de intrare, urmat de un spat iu si apoi valorile
ce alc atuiesc codul num arului, separate dou a cate dou a printr-un singur spat iu.
Restrict ii si precizari
2 N 18
Separatorul ntre partea ntreag a si partea zecimala este virgula.
Orice num ar are dupa virgula cel mult 5 cifre.
Valorile din codurile numerelor din sierele de test trebuie s a e cuprinse
n intervalul [106, 106].
Partea ntreag a a ecarui num ar real este o valoare mai mica sau egal a cu
20000.
Toate numerele din sierele de test sunt strict pozitive si distincte dou a
cate dou a.
Numarul maxim de valori utilizat pentru codicarea unui num ar este 2500.
16.2. CODURI - ONI 2007 417
Daca exista mai multe solut ii de codicare, se va asa una singur a.
Nu trebuie s a existe dou a numere diferite cu aceeasi codicare.
40% din teste vor cont ine numai numere ntregi, 30% din teste vor cont ine
numere ntregi si numere reale far a perioad a si 30% din teste vor cont ine numere
ntregi si numere reale cu si far a perioad a.
Exemplu
coduri.in coduri.out Explicat ii
8 2 1 1
10 3 -1 0 1 10=2*5 iar suma codurilor pentru 2 si 5
2 3 1 1 0 determin a codul lui 10
5 3 2 1 0
0,3 3 -1 2 1 2,1=7*0,3 iar suma codurilor pentru 7 si 0,3
7 3 1 3 1 determin a codul lui 2,1
2,1 2 1 11
1,(7) 2 1 2
1,2(34)
Timp maxim de execut ie/test(Windows/Linux): 0.2 secunde
16.2.1 Indicat ii de rezolvare - descriere solut ie *
Descrierea solut iei (Prof. Roxana Tmplaru)
O solut ie de codicare porneste de la ideea ca orice num ar ntreg se descom-
pune n factori primi, sub forma 2
k
1
3
k
2
5
k
3
7
k
4
...a
k
p
. Codicarea acestui
num ar va avea k
p
valori, iar acestea vor coecient ii la care apar factorii primi n
descompunerea num arului, adica k
p
...k
3
k
2
k
1
.
Numarul rezultat prin nmult irea a dou a numere va avea coecient ii n de-
scompunere suma coecient ilor celor dou a numere, deci codicarea num arului care
va rezulta ca produs a celor dou a, va rezulta din suma codurilor acestor numere.
Pentru numerele cu virgula, se foloseste scrierea sub forma de fract ie, se
descompune num ar atorul si numitorul, iar codicarea se va obt ine sc azand din
coecient ii de la num ar ator pe cei de la numitor.
16.2.2 Rezolvare detaliata
16.2.3 Codul sursa *
Rezultatele nu corespund cu cele date n exemplu dar ... pare corect aici!
import java.io.*;
418 CAPITOLUL 16. ONI 2007 CLASA A IX-A
class coduri
{
static BufferedReader br;
static PrintWriter out;
static int n;
static String nr;
static int[] p=new int[9593]; // nr prime
static int[] f1=new int[9593];
static int[] f2=new int[9593];
static int iuf, iuf1, iuf2;
public static void main(String[] args) throws IOException
{
int i,j,k;
int nr1,nr2,nr3,aux,n10,x,y;
br=new BufferedReader(new FileReader("coduri.in"));
out=new PrintWriter(new BufferedWriter(new FileWriter("coduri.out")));
nrprime();
n=Integer.parseInt(br.readLine());
for(i=1;i<=n;i++)
{
nr=br.readLine();
nr1=0;
for(j=0;j<nr.length();j++)
if(nr.charAt(j)==,) break;
else nr1=nr1*10+nr.charAt(j)-0;
//System.out.print(i+" : "+nr+" --> ");
if(j==nr.length()) // intreg
{
x=nr1;
y=1;
//System.out.println("x = "+x+" y = "+y);
if(x==1) // 1 nu se mai desxcompune ... are codul "0"
{
out.println("1 0");
continue;
}
16.2. CODURI - ONI 2007 419
descfact(x,f1);
iuf1=iuf;
out.print(iuf1+" ");
for(k=iuf1;k>=2;k--) out.print(f1[k]+" ");
out.println(f1[1]);
continue;
}// if intreg
nr2=0;
for(k=j+1;k<nr.length();k++)
if(nr.charAt(k)==() break;
else nr2=nr2*10+nr.charAt(k)-0;
if(k==nr.length()) // real neperiodic
{
x=nr1;
y=1;
aux=nr2;
while(aux!=0) { x*=10; y*=10; aux/=10;}
x+=nr2;
descfact(x,f1);
iuf1=iuf;
descfact(y,f2);
iuf2=iuf;
iuf=max(iuf1,iuf2);
out.print(iuf+" ");
for(k=iuf;k>=2;k--)
{
if(k<=iuf1 && k<=iuf2) out.print((f1[k]-f2[k])+" "); else
if(k<=iuf1)
out.print(f1[k]+" ");
else
out.print(-f2[k]+" ");
}
out.println(f1[1]-f2[1]);
continue;
}// if real neperiodic
420 CAPITOLUL 16. ONI 2007 CLASA A IX-A
// real periodic (nr1-nr2)/nr3
aux=nr2;
n10=1;
while(aux!=0) {nr1*=10; aux/=10; n10=n10*10;}
nr1+=nr2;
nr2=nr1;
nr3=0;
for(j=k+1;j<nr.length()-1;j++)
{
nr1=nr1*10+nr.charAt(j)-0;
nr3=nr3*10+9;
}
nr3=nr3*n10;
x=nr1-nr2;
y=nr3;
descfact(x,f1);
iuf1=iuf;
descfact(y,f2);
iuf2=iuf;
iuf=max(iuf1,iuf2);
out.print(iuf+" ");
for(k=iuf;k>=2;k--)
{
if(k<=iuf1 && k<=iuf2) out.print((f1[k]-f2[k])+" "); else
if(k<=iuf1)
out.print(f1[k]+" ");
else
out.print(-f2[k]+" ");
}
out.println(f1[1]-f2[1]);
}// for i
out.close();
}// main(...)
static void descfact(int nr, int[] f)
{
int i;
i=1;
f[1]=0;
while(nr>1)
16.3. LACURI - ONI 2007 421
{
while(nr%p[i]==0) {f[i]++; nr/=p[i];}
i++;
f[i]=0;
}
iuf=i-1;
}// descfact(...)
static void nrprime()
{
int i,j;
boolean ok;
int k;
p[1]=2; p[2]=3; p[3]=5; p[4]=7; p[5]=11;
p[6]=13; p[7]=17; p[8]=19; p[9]=23; // gata ...
k=9;
for(i=29;i<=99999;i=i+2)
{
ok=true;
for(j=2; j<=k && p[j]*p[j]<=i && ok; j++)
if(i%p[j]==0) ok=false;
if(ok)
{
p[++k]=i;
}
}// for
}// nrprime(...)
static int max(int a, int b)
{
if(a>b) return a; else return b;
}// max(...)
}// class
16.3 Lacuri - ONI 2007
Pe un teren de forma patrata sunt zone de uscat si lacuri. Harta terenului
este memorat a ntr-un tablou bidimensional n n cu valori 1 (apa) sau 0 (uscat).
Liniile sunt numerotate de la 1 la n, de sus n jos si coloanele de la 1 la n, de
la stanga la dreapta. Fiecare lac este nconjurat de o suprafat a de teren uscat.
Except ie fac doar lacurile situate la marginea terenului care sunt nconjurate de
uscat doar prin interiorul terenului nu si prin afara acestuia.
422 CAPITOLUL 16. ONI 2007 CLASA A IX-A
Cerint a
Se doreste s a se traverseze terenul pe uscat, de la pozit ia (1, 1) la pozit ia
(n, n), pe un drum de lungime minima, merg and pas cu pas. La un pas, se ajunge
de la un patrat el la altul nvecinat cu el spre nord, est, sud sau vest.
Sa se scrie un program care:
a) Determina num arul lacurilor care sunt de forma patrata si n acelasi timp
sunt pline de 1.
b)
In cazul n care toate lacurile sunt de forma patrata si n acelasi timp
pline de 1, determinat i un drum cu proprietatea de mai sus.
Date de intrare
Fisierul de intrare lacuri.in are pe prima linie num arul n, iar pe urmatoarele
n linii este harta terenului (ecare linie are n valori 0 sau 1, separate de cate un
spat iu).
Date de iesire
Fisierul de iesire lacuri.out va cont ine:
pe prima linie: num arul de lacuri ce sunt de forma patrata si n acelasi timp
pline de 1;
n cazul n care toate lacurile sunt de forma patrata si n acelasi timp pline
de 1, urmeaz a liniile ce descriu drumul de lungime minima ales. Fiecare linie din
sier cont ine cate o pereche de coordonate ale pozit iilor succesive prin care trece
drumul (linia si coloana, separate cu un spat iu), ncepand cu (1, 1) si terminand
cu (n, n).
Restrict ii si precizari
2 n 100
Pozit iile (1, 1) si (n, n) sunt sigur libere (cu valoarea 0).
Daca exista mai multe solut ii se va asa oricare dintre ele.
Pot cel mult 100 de lacuri si cel put in unul; dac a un lac este de forma
patrata, atunci 1 latura n 1.
Indiferent de forma lor, lacurile sunt sigur izolate, adica nu se ating
deloc de alt lac. De exemplu, dac a un lac cont ine pozit ia (3, 3), atunci un alt lac nu
poate cont ine vreuna din pozit iile nvecinate cu (3, 3), adica: (2, 3), (2, 4), (3, 4),
(4, 4), (4, 3), (4, 2), (3, 2) si (2, 2).
Pentru cerint a a) se acorda 30% din punctaj, iar pentru cerint a b) se acorda
70% din punctaj.
Exemplu
16.3. LACURI - ONI 2007 423
lacuri.in lacuri.out
6 4
0 0 0 0 0 0 1 1
0 1 0 1 1 1 1 2
0 0 0 1 1 1 1 3
0 0 0 1 1 1 2 3
1 1 0 0 0 0 3 3
1 1 0 0 1 0 4 3
5 3
5 4
5 5
5 6
6 6
Explicat ie:
a) Prima linie cont ine 4 (sunt 4 lacuri de forma patrata si pline de 1)
b) Deoarece toate cele 4 lacuri sunt de forma patrata si pline de 1, se scrie
si drumul ales: de la (1, 1), (1, 2), (1, 3), (2, 3), (3, 3), ...., (6, 6).
Observat ii:
1) Daca n pozit ia (3, 5) ar fost un 0, atunci lacul cu latura 3 nu ar mai
fost plin de 1 si atunci prima linie ar cont inut doar valoarea 3 (ar fost doar
3 lacuri patrate si pline de 1).
2) n exemplul init ial, dac a n pozit ia (6, 1) ar fost valorea 0, atunci nu ar
fost toate lacurile patrate (cel din stanga-jos nu ar fost patrat) si s-ar asat
doar un 3 n ?ierul de iesire.
3) n exemplul init ial, dac a n pozit ia (5, 2) ar fost valoarea 0, atunci s-ar
asat doar un 3, pentru ca lacul din stanga-jos nu ar un lac patrat si plin de
1.
Timp maxim de execut ie/test: 0.25 secunde
16.3.1 Indicat ii de rezolvare - descriere solut ie *
Descrierea solut iei (Prof. Dan Grigoriu)
a. Prima cerint a: se parcurge tabloul pe linii si pentru ecare valoare 1
nt alnit a se verica dac a este colt ul stanga-sus al unui patrat ; dac a da, atunci
se num ar a si se sterge acel patrat; dac a nu, atunci se ret ine acest lucru. Apoi se
reia cautarea unei eventuale alte valori 1.
b. A doua cerint a: dac a toate lacurile sunt patrate si pline de 1, atunci se
ncearc a un drum apropiat de diagonal a de la pozit ia (1, 1) la pozit ia (n, n); sigur
va exista un asemenea drum deoarece lacurile sunt izolate si pot ocolite.
Fie pozit ia curent a (i, i). Cazuri:
1. pozit ia (i + 1, i + 1) este ocupat a.
424 CAPITOLUL 16. ONI 2007 CLASA A IX-A
In ecare casut a este scris cate un num ar ntreg din intervalul [100, 100].
Fiecare jucator are cate o piatra pe care o arunc a ntr-o casut a a sotronului, si
s arind ntr-un picior, mpinge piatra din casut a n casut a, pe un anumit traseu
astfel ncat punctajul obt inut din suma numerelor de pe traseul parcurs s a e cat
mai mare.
Numerele din casut ele sotronului sunt scrise cu dou a culori albastru si alb,
astfel ncat s a nu existe dou a casut e al aturate (pe cele patru direct ii Nord, Est,
Sud, Vest) av and numere scrise cu aceeasi culoare.
Intotdeauna, prima casut a din
primul r and al sotronului are nscris un num ar de culoare albastr a.
Se stabilesc apoi, urmatoarele reguli ale jocului:
- la nceputul jocului, piatra poate aruncata n oricare casut a a sotronului.
Din pozit ia respectiv a jucatorul si conduce piatra pana la sfarsitul traseului sta-
bilit de el;
- dintr-o casut a n care num arul este scris cu albastru, piatra poate de-
plasata doar n casut a vecin a pe direct ia Nord;
- dintr-o casut a n care num arul este scris cu alb, piatra poate deplasat a
doar n casut a vecin a pe direct ia Est;
- jucatorul poate alege orice casut a (inclusiv cea n care a aruncat piatra)
pentru a ncheia jocul, at ata timp cat piatra nu iese din sotron.
Cerint a
432 CAPITOLUL 16. ONI 2007 CLASA A IX-A
Sa se scrie un program care s a determine cel mai mare punctaj care se poate
obt ine jucand sotron dupa regulile stabilite.
Date de intrare
Fisierul de intrare sotron.in are pe prima linie dimensiunea n a sotronului,
iar pe urmatoarele n linii cate n numere separate de cate un spat iu, reprezent and
numerele scrise n sotron.
Date de iesire
Fisierul de iesire sotron.out va cont ine pe prima linie un singur num ar
reprezent and punctajul maxim care se poate obt ine jucand sotron.
Restrict ii si precizari
1 n 240
Exemplu
secv.in secv.out Explicat ii
5 21
0 -6 -5 -17 2 Punctajul obt inut este
1 -4 7 10 5 3+(-2)+3+7+10=21
-3 -2 3 -8 -8
-20 3 5 3 -5
-10 -15 2 2 -4
Timp maxim de execut ie/test(Windows/Linux): 0.1 secunde
16.5.1 Indicat ii de rezolvare - descriere solut ie *
Descrierea solut iei (Prof. Cristina Barbieru)
Se deplaseaz a piatra n sotron din casut a n casut a, conform regulilor din
enunt , identicandu-se astfel n trasee(n forma de zig-zag) de lungime (num ar de
casut e) maxima posibil a. Aceste trasee pornesc din ecare casut a n care e scris un
num ar cu albastru, de pe prima coloana a sotronului sau dintr-o casut a cu num ar
scris cu alb de pe ultima linie a sotronului.
Pentru a calcula punctajul maxim obt inut de un jucator, se calculeaz a pentru
ecare astfel de traseu suma maxima a numerelor unei succesiuni de casut e vecine.
16.5. SOTRON - ONI 2007 433
Numerele scrise ntr-un traseu determinant la un moment dat se pot memora ntr-
un vector, astfel, acest a problema este echivalent a cu determinarea unei secvent e
de suma maxima dintr-un vector.
16.5.2 Rezolvare detaliata
16.5.3 Codul sursa *
import java.io.*;
class Sotron
{
static StreamTokenizer st;
static PrintWriter out;
static int n,smaxsol=-101;
static int[][] a;
static int[] x;
public static void main(String[] args) throws IOException
{
int i,j,ii,jj,nc,smaxc;
st=new StreamTokenizer(new BufferedReader(new FileReader("sotron.in")));
out=new PrintWriter(new BufferedWriter(new FileWriter("sotron.out")));
st.nextToken(); n=(int)st.nval;
a=new int[n+1][n+1];
x=new int[2*n];
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
st.nextToken(); a[i][j]=(int)st.nval;
}
// prima coloana
for(i=1;i<=n;i++)
{
if(i%2==0) continue;
nc=0;
434 CAPITOLUL 16. ONI 2007 CLASA A IX-A
x[++nc]=a[i][1];
ii=i-1;
jj=1;
while(ii>=1)
{
x[++nc]=a[ii][jj]; // sus
x[++nc]=a[ii][++jj]; // dreapta
ii--;
}
smaxc=secvsummax(nc);
if(smaxc>smaxsol) smaxsol=smaxc;
}// for i
// ultima linie
for(j=1;j<=n;j++)
{
if(n%2==0 && j%2==0) continue;
if(n%2==1 && j%2==1) continue;
nc=0;
x[++nc]=a[n][j];
ii=n;
jj=j+1;
while(jj<=n)
{
x[++nc]=a[ii][jj]; // dreapta
x[++nc]=a[--ii][jj]; // sus
jj++;
}
smaxc=secvsummax(nc);
if(smaxc>smaxsol) smaxsol=smaxc;
}// for j
out.println(smaxsol);
out.close();
}// main(...)
static int secvsummax(int n)
{
int i,i1,i2,ic,sc,smax;
i1=i2=ic=1;
smax=sc=x[1];
for(i=2;i<=n;i++)
{
16.6. TRIUNGHI - ONI 2007 435
if(sc<=0) { ic=i; sc=x[i]; continue; } else sc=sc+x[i];
if(sc>=smax) { smax=sc; i1=ic; i2=i; }
}
//System.out.println("smax = "+smax+" x["+i1+"..."+i2+"]");
return smax;
}// secvsummax(...)
}// class
16.6 Triunghi - ONI 2007