Académique Documents
Professionnel Documents
Culture Documents
Note de Laborator
(uz intern - draft v1.8)
Adrian Rabaea
Cuprins
1 Exercitii simple
1.1 Algoritmi elementari . . . . . . . . . . . . . . . . . . . .
1.1.1 Acest num
ar este prim? . . . . . . . . . . . . . .
1.1.2 Lista numerelor prime . . . . . . . . . . . . . . .
1.1.3 Descompunere n factori primi . . . . . . . . . .
1.1.4 Cel mai mare divizor comun . . . . . . . . . . . .
1.1.5 Cel mai mic multiplu comun . . . . . . . . . . .
1.1.6 Cel mai mic multiplu comun, optimizat . . . . .
1.1.7 Calculul puterilor . . . . . . . . . . . . . . . . . .
1.1.8 Calculul puterilor, optimizat . . . . . . . . . . .
1.1.9 Calculul factorialului . . . . . . . . . . . . . . . .
1.1.10 Calculul combin
arilor . . . . . . . . . . . . . . .
1
n
. . . . . . . .
C2n
1.1.11 Numarul lui Catalan Cn = n+1
1.1.12 Produsul a dou
a polinoame . . . . . . . . . . . .
1.1.13 Schema lui Horner . . . . . . . . . . . . . . . . .
1.1.14 Calculul valorii unui polinom . . . . . . . . . . .
1.1.15 Puterea unui polinom . . . . . . . . . . . . . . .
1.1.16 Derivata unui polinom . . . . . . . . . . . . . . .
1.1.17 Derivata de ordinul k a unui polinom . . . . . . .
1.1.18 Derivata de ordinul k a functiei f (x) = Pn (x)ex
1.1.19 Ordinul unei permutari . . . . . . . . . . . . . .
1.1.20 Suma puterilor r
adacinilor ecuatiei de grad 2 . .
1.1.21 Suma puterilor r
adacinilor ecuatiei de grad 3 . .
1.1.22 S
irul lui Fibonacci si proportia de aur . . . . .
1.1.23 Descompunere Fibonacci . . . . . . . . . . . . .
1.1.24 Numarul permutarilor idempotente . . . . . . . .
1.1.25 Fractie continua: determinarea coeficientilor . . .
1.1.26 Fractie continua: determinarea fractiei initiale . .
1.1.27 Generare polinom cu r
adacini fractionare date .
1.1.28 Radacini rationale . . . . . . . . . . . . . . . . .
1.1.29 Numarul divizorilor unui num
ar natural . . . . .
1.1.30 Functia lui Euler . . . . . . . . . . . . . . . . . .
iii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
1
1
2
2
3
4
5
7
7
8
8
10
11
12
13
13
14
15
16
17
19
19
20
21
22
22
23
24
25
26
27
1.2
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
28
28
30
31
32
32
33
34
35
1
1
Calcul f (n) = n! 1 1!
. . . . . . . . .
+ 2!
... + (1)
n!
Pm1 k
k
n
Calcul s(n, m) = k=0 Cm (1) (m k) . . . . . . . . . .
n
n
1 1
... Cm+n1
Calcul f (m, n, 1 , ..., n ) = Cm
. . . . .
1 1
n
Pm
mk
k
n
Calcul f (...) = k=1 (1)
Cm Ck
... Ck+n1
.
P
n
Calcul f (n) = 21n k=0 (1)k Cnk 2k (2n k)! . . . . . . . . .
Numerele Stirling de speta a II-a . . . . . . . . . . . . . . .
Numerele lui Bell . . . . . . . . . . . . . . . . . . . . . . . .
Partitiile unui num
ar natural
Pn . . . . . . . . . . . . . . . . .
Recurenta Catalan: Cn = k=1 Ck1 Cnk unde C0 = 1 . .
Recurenta: En = E2 En1 + E3 En2 + ... + En1 E2 unde
E 1 = E2 = 1 . . . . . . . . . . . . . . . . . . . . . . . . . .
Numerele Stirling
Pn de speta a II-a . . . . . . . . . . . . . . .
Calcul f (n) = Pk=0 Cnk Fk . . . . . . . . . . . . . . . . . . .
n
Calcul f (n) = k=0 Cnk 2k Fk . . . . . . . . . . . . . . . . .
37
1.2.5
1.2.6
1.2.7
1.2.8
1.2.9
1.2.10
1.2.11
1.2.12
1.2.13
1.2.14
1.2.15
1.2.16
1.2.17
37
39
40
42
43
44
45
46
47
48
50
51
53
53
53
54
55
57
59
61
63
66
66
68
72
76
79
82
2.2.7
2.2.8
2.2.9
2.2.10
2.2.11
2.2.12
2.2.13
2.2.14
.
*
.
.
.
*
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
109
109
110
110
110
112
113
113
113
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
117
117
118
119
119
121
122
122
122
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
125
125
126
127
127
132
133
134
134
.
*
.
.
.
*
.
.
.
*
.
.
.
*
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
137
137
138
138
138
139
140
141
141
.
*
.
.
.
*
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
145
145
146
147
147
150
151
152
152
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
157
157
160
160
162
164
165
165
168
169
170
171
171
173
175
175
175
177
178
178
178
181
183
183
8.6.3
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
195
195
196
197
198
200
200
201
201
202
202
203
204
205
206
206
206
208
209
209
209
211
212
213
213
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
215
215
216
217
217
218
219
221
225
229
230
231
231
232
233
233
.
.
*
.
.
.
*
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
238
242
243
244
244
246
247
248
248
.
*
.
.
.
*
.
.
.
*
.
.
.
*
.
.
.
*
.
.
.
*
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
251
251
252
252
252
256
257
258
258
261
262
263
263
266
268
268
270
271
272
273
273
274
275
276
276
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
279
279
280
280
281
281
283
283
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
287
289
290
291
291
295
296
297
297
299
300
300
300
301
302
303
303
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
307
307
308
309
311
317
319
321
321
322
323
323
323
335
336
337
337
340
342
344
344
350
351
352
352
x
14 ONI 2006 clasa a IX-a
14.1 Factorial . . . . . . . . . . .
14.1.1 Indicatii de rezolvare
14.1.2 Rezolvare detaliat
a .
14.1.3 Codul sursa * . . . .
14.2 Limbaj . . . . . . . . . . . .
14.2.1 Indicatii de rezolvare
14.2.2 Rezolvare detaliat
a .
14.2.3 Codul sursa * . . . .
14.3 Panouri . . . . . . . . . . .
14.3.1 Indicatii de rezolvare
14.3.2 Rezolvare detaliat
a .
14.3.3 Codul sursa * . . . .
14.4 Pereti . . . . . . . . . . . .
14.4.1 Indicatii de rezolvare
14.4.2 Rezolvare detaliat
a .
14.4.3 Codul sursa * . . . .
14.5 Sant . . . . . . . . . . . . .
14.5.1 Indicatii de rezolvare
14.5.2 Rezolvare detaliat
a .
14.5.3 Codul sursa * . . . .
14.6 Zumzi . . . . . . . . . . . .
14.6.1 Indicatii de rezolvare
14.6.2 Rezolvare detaliat
a .
14.6.3 Codul sursa * . . . .
.
*
.
.
.
*
.
.
.
*
.
.
.
*
.
.
.
*
.
.
.
*
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
357
357
358
358
358
360
361
362
362
368
369
370
370
374
375
375
375
377
379
379
379
381
383
384
385
Capitolul 1
Exercitii simple
1.1
Algoritmi elementari
1.1.1
Acest num
ar 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
1.1.2
CAPITOLUL 1. EXERCIT
II SIMPLE
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
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.4
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));
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
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.6
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)
{
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.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
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)
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 combin
arilor
10
CAPITOLUL 1. EXERCIT
II SIMPLE
}
return d;
}
1.1.11
Num
arul lui Catalan Cn =
1
Cn
n+1 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.12
Produsul a dou
a 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;
11
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
13
}// main
}// class
1.1.14
1.1.15
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
class DerivataPolinom
{
public static void main(String[] args)
{
int gradp=3; // gradul polinomului p
int[] p=new int[gradp+1];
1.1.17
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;
15
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
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.19
import java.io.*;
class OrdinPermutare
{
static int n;
static int[] pr;
static int[] p;
public static void main(String[] args) throws IOException
17
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.20
Suma puterilor r
ad
acinilor ecuatiei 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 r
ad
acinilor ecuatiei 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;
19
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
S
irul lui Fibonacci si proportia 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]);
}
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
Num
arul permut
arilor idempotente
1.1.25
Fractie continu
a: determinarea coeficientilor
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.26
Fractie continu
a: determinarea fractiei initiale
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];
23
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 r
ad
acini fractionare date
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
R
ad
acini rationale
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;
}
1.1.29
Num
arul divizorilor unui num
ar 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.30
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;
}
}
27
28
CAPITOLUL 1. EXERCIT
II SIMPLE
1.1.31
Formul
a de calcul pentru functia 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 num
arul
Se alege un num
ar natural ntre 1 si n. Calculatorul n
treaba cum este fata
de mijlocul extremelor curente (de la fiecare pas). Numarul se ghiceste n maxim
1 + [log2 (n)] pasi (ntrebari).
29
30
CAPITOLUL 1. EXERCIT
II SIMPLE
{
scrieText("Cum este fata de "+m+" ?");
scrieText("1 = mai mic; 2 = mai mare;
raspuns = getInt();
3 = EGAL
raspuns: ");
}
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
arcsin(x) = x +
x x (2k 1) (2k 1)
tk pentru k 1
2k(2k + 1)
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
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
1.2.1
1.2.2
Calcul f (n) =
Pn
1
n
k=0 2k Cn+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;
33
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) =
Pn1
k=0
k
Cn1
nn1k (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.4
class SP03
Pn1
k=1
Cnk k k1 (n k)nk
35
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;
}
37
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 fixe.
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) =
Pm1
k=0
k
Cm
(1)k (m k)n
s(n, m) reprezint
a num
arul functiilor 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;
39
1.2.7
1
n
Calcul f (m, n, 1 , ..., n ) = (Cm
) 1 ... Cm+n1
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;
n
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 (...) =
Pm
mk
k=1 (1)
1 1
n
k
n
Cm
(Ck ) ... Ck+n1
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;
41
42
CAPITOLUL 1. EXERCIT
II SIMPLE
1.2.9
Calcul f (n) =
1
2n
Pn
k k k
k=0 (1) Cn 2 (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;
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
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
n
X
k=0
45
1.2.12
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
Recurenta Catalan: Cn =
Pn
k=1
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
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
m1
1 X
k
(1)k Cm
(m k)n .
m!
k=0
49
50
CAPITOLUL 1. EXERCIT
II SIMPLE
1.2.16
Calcul f (n) =
Pn
k=0
Cnk Fk
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.17
Calcul f (n) =
Pn
k=0
Cnk 2k Fk
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]);
}
51
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 operatiilor cu
numere mari
2.1
2.1.1
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
2.1.2
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
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
55
56
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
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
Imp
artirea 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)
57
58
2.1. OPERAT
II CU NUMERE MARI
59
b[k]=a[k]/2;
t=a[k]%2;
}
}
return b;
}
}
2.1.5
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
2.1. OPERAT
II CU NUMERE MARI
}
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
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;
61
62
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 combin
arilor 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
2.1. OPERAT
II CU NUMERE MARI
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;
}
}
}
65
66
2.2
2.2.1
Num
arul lui Catalan Cn =
1
Cn
n+1 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;}
67
68
2.2.2
Calcul f (n) =
Pn
1
n
k=0 2k Cn+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++)
69
70
71
72
2.2.3
Calcul f (n) =
Pn1
k=0
k
Cn1
nn1k (k + 1)! cu numere mari
class SP02NrMari
{
public static void main(String[]args)
{
int n=12;
int[] s;
int[] p;
73
74
75
76
}
}
}// class
2.2.4
Pn1
k=1
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];
77
78
79
2.2.5
1
n
Calcul f (m, n, 1 , ..., n ) = (Cm
) 1 ... Cm+n1
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;
n
cu numere
80
81
82
2.2.6
83
84
}
}//class
2.2.7
n
X
k=0
85
86
87
88
2.2.8
89
90
2.2.9
Recurenta Catalan Cn =
cu numere mari
Pn
k=1
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);
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;
}
91
92
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
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
95
96
2.2.11
Calcul f (n) =
Pn
k=0
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]);
}
}
97
98
2.2.12
Calcul f (n) =
Pn
k=0
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]);
99
100
101
102
103
2.2.13
Fractie continu
a: determinarea fractiei initiale cu numere 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
}
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;
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
Num
arul permut
arilor idempotente, cu numere mari
106
107
108
}
}
Capitolul 3
Poarta
110
poarta.out
4
3.1.1
Indicatii de rezolvare *
3.1.2
Rezolvare detaliat
a
3.1.3
Codul surs
a*
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
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;
}
111
112
3.2
Mouse
113
3.2. MOUSE
mouse.in
24
1263
3412
mouse.out
7 21
11
21
22
12
13
14
24
Explicatie
3.2.1
Indicatii de rezolvare *
3.2.2
Rezolvare detaliat
a
3.2.3
Codul surs
a*
import java.io.*;
class Mouse
{
static int m,n,imin,jmin,min,s;
static int [][]a;
114
3.2. MOUSE
j=1;
out.println(m*n+" "+s);
while(j+1<n)
{
for(i=1;i<=m;i++) out.println(i+" "+j);
j++;
for(i=m;i>=1;i--) out.println(i+" "+j);
j++;
}
for(i=1;i<=m;i++) out.println(i+" "+n);
}
static void mnpare()
{
int i,j;
imin=0;jmin=0;min=101;
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
if((i+j)%2==1)
if(a[i][j]<min) { min=a[i][j]; imin=i; jmin=j; }
out.println((m*n-1)+" "+(s-a[imin][jmin]));
j=1;
while(j+1<jmin) // stanga
{
for(i=1;i<=m;i++) out.println(i+" "+j);
j++;
for(i=m;i>=1;i--) out.println(i+" "+j);
j++;
}
i=1;
while(i+1<imin) // sus
{
out.println(i+" " +j);
out.println(i+" " +(j+1));
out.println((i+1)+" " +(j+1));
out.println((i+1)+" " +j);
i=i+2;
}
out.println(i+" "+j); // patratel
if((i==imin)&&(j+1==jmin)) out.println((i+1)+" " +j);
else out.println(i+" " +(j+1));
115
116
}
}//class
Capitolul 4
Text
Vasile lucreaz
a intens la un editor de texte. Un text este format din unul sau
mai multe paragrafe. Orice paragraf se termina cu Enter si oricare dou
a cuvinte
consecutive din acelasi paragraf sunt separate prin spatii (unul sau mai multe). In
functie de modul de setare a paginii, num
arul maxim de caractere care ncap n
pagina pe o linie este unic determinat (Max).
Functia pe care Vasile trebuie s
a o implementeze acum este alinierea n pagina
a fiecarui paragraf din text la stanga si la dreapta. Pentru aceasta el va trebui s
a
mpart
a fiecare paragraf n linii separate de lungime Max (fiecare linie terminat
a
cu Enter).
Imp
artirea se realizeaza punand num
arul maxim posibil de cuvinte pe fiecare
linie, far
a mpartirea cuvintelor n silabe.
Pentru aliniere stanga-dreapta, Vasile trebuie s
a repartizeze spatii n mod
uniform ntre cuvintele de pe fiecare linie, astfel ncat ultimul caracter de pe
linie s
a fie diferit de spatiu, iar num
arul total de caractere de pe linie s
a fie egal
cu Max. Exceptie face numai ultima linie din paragraf, care r
amane aliniata la
stanga (cuvintele fiind separate printr-un singur spatiu, chiar dac
a linia nu este
plina).
In general, este putin probabil ca alinierea s
a fie realizabila prin plasarea
aceluiasi num
ar de spatii ntre oricare dou
a cuvinte consecutive de pe linie. Vasile
considera ca este mai elegant ca, dac
a ntre unele cuvinte consecutive trebuie plasat
un spatiu n plus fat
a de alte perechi de cuvinte consecutive, acestea s
a fie plasate
la nceputul liniei.
Cerint
a
Scrieti un program care s
a citeasc
a lungimea unei linii si textul dat si care s
a
alinieze textul la stanga si la dreapta.
117
118
Date de intrare
Fisierul de intrare text.in contine pe prima linie Max, lungimea maxima a
unui r
and. Pe urmatoarele linii este scris textul.
Date de iesire
Fisierul de iesire text.out contine textul aliniat stanga-dreapta.
Restrictii si preciz
uri
2 Max 1000.
Lungimea maxima a oric
arui cuvant din text este 25 caractere si nu depaseste
Max.
Lungimea unui paragraf nu depaseste 1000 de caractere.
Solutia este unic
a.
Exemple
text.in
20
Vasile are multe bomboane bune.
text.out
Vasile are multe
bomboane bune.
Explicatie
Pe prima linie au fost plasate cate 3 spatii ntre cuvintele consecutive.
text.in
20
Ana are mere.
Ion are multe pere galbene?
text.out
Ana are mere.
Ion are multe pere
galbene?
Explicatie
Intre Ion si are exist
a 2 spatii, ntre are si multe - 2 spatii, iar ntre multe
si pere - 1 spatiu.
Observati ca paragraful Ana are mere. (care are lungimea mai mica decat
20) a r
amas aliniat la stanga, iar ultima linie din fiecare paragraf r
amane aliniata
la stanga, cuvintele consecutive fiind separate printr-un singur spatiu.
Timp maxim de executare: 1 secunda/test.
4.1.1
Indicatii de rezolvare *
119
4.1. TEXT
4.1.2
Rezolvare detaliat
a*
21
E cerul sus
Ca niste-ntinse brate
N-au crengile de ce sa se agate
0000:0000
0000:0010
0000:0020
0000:0030
0000:0040
32
0A
20
6E
65
31
43
62
67
20
0D
61
72
69
61
0A
20
61
6C
67
45
6E
74
65
61
20
69
65
20
74
63
73
0D
64
65
65
74
0A
65
0D
72
65
4E
20
0A
75
2D
2D
63
1A
6C
6E
61
65
20
74
75
20
73
69
20
73
75
6E
63
61
73
73
72
20
0D
65
65
73
Sf
arsitul de fisier (EOF) este marcat prin 1A.
Sf
arsitul de linie (EOL) este marcat prin 0D0A.
4.1.3
Codul surs
a*
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
}
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
4.2
Numere
Gigel este un mare pasionat al cifrelor. Orice moment liber si-l petrece jucanduse 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 submultimi disjuncte de suma
egal
a.
Desigur, Gigel a crezut ca este o nt
amplare si a scris alte 10 numere distincte de cate dou
a cifre si spre surpriza lui, dupa un timp a g
asit din nou dou
a
submultimi disjuncte de sum
a egal
a.
Cerint
a
Date 10 numere distincte de cate dou
a cifre, determinati num
arul de perechi
de submultimi 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 fiecare
dintre cele dou
a submultimi este maxima.
Date de intrare
Fisierul de intrare numere.in contine pe prima linie 10 numere naturale
distincte separate prin cate un spatiu x1 x2 ... x10 .
Date de iesire
Fisierul de iesire numere.out contine trei linii. Pe prima linie se afla num
arul
de perechi de submultimi de suma egal
a, precum si suma maxima obtinuta, separate printr-un spatiu. Pe linia a doua se afla elementele primei submultimi, iar pe
linia a treia se afla elementele celei de a doua submultimi, separate prin cate un
spatiu.
122
NrSol - num
arul de perechi; Smax - suma maxima
elementele primei submultimi
elementele celei de a doua submultimi
Restrictii si preciz
ari
10 xi , yi 99, pentru 1 i 10.
1 k, p 9.
Ordinea submultimilor n perechi nu conteaza.
Perechea de submultimi determinata nu este obligatoriu unic
a.
Exemplu
numere.in
60 49 86 78 23 97 69 71 32 10
numere.out
130 276
78 97 69 32
60 49 86 71 10
Explicatie:
130 de solutii; suma maxima este 276; s-au folosit 9 din cele 10 numere; prima
submultime are 4 elemente, a doua are 5 elemente.
Timp maxim de executare: 1 secunda/test
4.2.1
Indicatii de rezolvare *
4.2.2
Rezolvare detaliat
a
4.2.3
Codul surs
a*
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
}
}// class
Capitolul 5
Expresie
Se da un sir de n numere naturale nenule x1 , x2 , ..., xn si un num
ar natural
m.
Cerint
a
ar natural.
Sa se verifice dac
a valoarea expresiei m x1 ...xn exte un num
In caz afirmativ s
a se afiseze acest num
ar descompus n factori primi.
Date de intrare
In fisierul exp.in se afla pe prima linie m, pe linia a doua n, iar pe linia a
treia numerele x1 , x2 , ..., xn separate ntre ele prin cate un spatiu.
Date de iesire
In fisierul exp.out se va scrie pe prima linie cifra 0, dac
a valoarea expresiei
nu este un num
ar natural, respectiv 1 dac
a este un num
ar natural. Daca valoarea
expresiei este un num
ar natural pe urmatoarele linii se vor scrie perechi de forma p
e (p este factor prim care apare n descompunere la puterea e 1). Aceste perechi
se vor scrie n ordine crescatoare dupa primul num
ar (adica p).
Restrictii si preciz
ari
n - num
ar natural nenul < 5000
xi - num
ar natural nenul < 30000, i 1, 2, ..., n
m - poate fi una din cifrele 2, 3, 4
Exemple
125
126
exp.out
0
exp.in
2
4
32 81 100 18
exp.out
1
24
33
51
5.1.1
Indicatii de rezolvare *
Solutie prezentat
a de Mihai Stroe, GInfo nr. 14/4
Rezolvarea problemei const
a n descompunerea n factori primi a numerelor date si prelucrarea acestor factori.
Concret, se poate pastra un vector P de la 1 la 30000, n care Pi este 0 dac
a
i nu este prim, respectiv puterea la care apare i n descompunerea n factori primi
a produsului dac
a i este prim.
Valorile din P nu pot depasi n log2 30000, deci vor fi mai mici sau egale cu
5000 14 = 70.000; astfel, elementele vectorului vor fi de tip longint.
Fiecare din cele n numere este descompus n factori primi. In momentul n
care se determin
a un factor prim F al unui num
ar din cele date, se incrementeaza
PF cu puterea la care F apare n descompunerea num
arului respectiv. Nu este
necesara memorarea separata a descompunerii fiecarui num
ar.
In final, pentru fiecare element din P se verifica dac
a este multiplu de m.
Daca toate elementele ndeplinesc aceast
a conditie, expresia este un num
ar
natural si se trece la afisare.
Se poate renunta la vectorul de 30000 de elemente, pastr
andu-se n locul
acestuia un vector n care se memoreaz
a numerele prime mai mici decat 30000
si un vector care arata la ce puteri apar aceste numere n descompunere. Aceast
a
abordare introduce n plus operatii pentru a g
asi indicele unui anumit num
ar prim;
se poate folosi cu succes cautarea binara. Pe de alta parte, la descompunerea n
factori primi se va testa numai mpartirea prin numere prime.
Analiza complexit
atii
Descompunerea
unui
num
ar x n factori primi are ordinul de complexitate
5.1. EXPRESIE
5.1.2
Rezolvare detaliat
a
5.1.3
Codul surs
a*
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)
127
128
}
}
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
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
}
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
133
5.2. REACTIVI
Date de intrare
Fisierul de intrare react.in contine:
pe prima linie num
arul natural N , care reprezint
a num
arul de reactivi;
pe fiecare dintre urmatoarele N linii se afla min max (doua numere ntregi
separate printr-un spatiu); numerele de pe linia x + 1 reprezint
a temperatura
minima, respectiv temperatura maxima de stocare a reactivului x.
Date de iesire
Fisierul de iesire react.out va contine o singur
a linie pe care este scris
num
arul minim de frigidere necesar.
Restrictii si preciz
ari
1 N 8000
100 minx maxx 100 (numere ntregi, reprezent
and grade Celsius),
pentru orice x de la 1 la N
un frigider poate contine un num
ar nelimitat de reactivi
Exemple
react.in
3
-10 10
-25
20 50
react.out
2
react.in
4
25
57
10 20
30 40
react.out
3
react.in
5
-10 10
10 12
-20 10
7 10
78
react.out
2
5.2.1
Indicatii de rezolvare *
Solutie prezentat
a de Mihai Stroe, GInfo nr. 14/4
Problema se poate rezolva prin metoda greedy.
O variant
a mai explicit
a a enuntului este urmatoarea:
Se consider
a N intervale pe o ax
a. S
a se aleag
a un num
ar minim de puncte
astfel nc
at fiecare interval s
a contin
a cel putin unul dintre punctele alese.
Facem o prim
a observatie: pentru orice solutie optim
a exista o solutie cu
acelasi num
ar de puncte (frigidere), n care fiecare punct s
a fie sfarsitul unui interval. Aceasta se poate obtine mutand fiecare punct spre dreapta, pana cand ar
ajunge la sfarsitul intervalului care se termina cel mai repede, dintre intervalele
care l contin. Se observa ca noua solutie respecta restrictiile din enunt.
In continuare ne vom concentra pe g
asirea unei solutii de acest tip.
Sort
am reactivii dupa sf
arsitul intervalului. Pentru intervalul care se termina
cel mai repede, alegem ultimul punct al s
au ca temperatur
a a unui frigider. Se
observa ca aceast
a alegere este cea mai buna, dintre toate alegerile unui punct
134
5.2.2
Rezolvare detaliat
a
5.2.3
Codul surs
a*
import java.io.*;
class Reactivi
{
static int n;
static int ni=0;
static int nf=0;
static int[] ngf;
static int[] x1,x2;
//
//
//
//
//
n=nr reactivi
ni=nr interschimbari in quickSort
n=nr frigidere
ng=nr grade in frigider
limite inferioara/superioara
5.2. REACTIVI
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("Reactivi.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("Reactivi.out")));
st.nextToken(); n=(int)st.nval;
x1=new int[n+1];
x2=new int[n+1];
ngf=new int[n+1];
for(i=1;i<=n;i++)
{
st.nextToken(); x1[i]=(int)st.nval;
st.nextToken(); x2[i]=(int)st.nval;
}
sol();
out.println(nf);
out.close();
}// main
static void sol()
{
int i;
quickSort(1,n);
i=1; nf=1; ngf[nf]=x2[i];
i++;
while(i<n)
{
while((i<=n)&&(x1[i]<=ngf[nf])) i++;
if(i<n) ngf[++nf]=x2[i++];
}
}
static void quickSort(int p, int u)
{
int i,j,aux;
i=p; j=u;
while(i<j)
{
while((i<j)&&((x2[i]<x2[j])||
((x2[i]==x2[j])&&(x1[i]>=x1[j])))) i++;
if(i!=j)
{
aux=x1[i]; x1[i]=x1[j]; x1[j]=aux;
aux=x2[i]; x2[i]=x2[j]; x2[j]=aux;
}
135
136
}
}
Capitolul 6
Numere
138
numere.out
24
Explicatie
In fisierul de intrare au fost nlocuite cu 0
numerele 2, 3, 4.
6.1.1
Indicatii de rezolvare *
Solutia oficial
a
Se foloseste un vector cu componente 0 sau 1, x = (x1 , ..., xm ), unde m
este 64000 dac
a num
arul de componente al tabloului (n2 ) este mai mare decat
64000, respectiv m = n2 n celalalt caz.
Initial vectorul x are toate componentele 0. Pe masura ce se citesc numere v
din fisier, componentele corespunzatoare din x se schimba n 1 (xv := 1).
Dup
a citirea numerelor din fisier se obtine n x o secventa de 0. Indicii corespunzatori acestei secvente formeaz
a multimea de numere consecutive care au fost
nlocuite cu 0 de fratele lui Mircea.
O alta modalitate de rezolvare const
a n calculul sumei tuturor numerelor
din tablou si obtinerea astfel a sumei secventei de numere consecutive sterse de
Mircea. Din pacate sumele sunt prea mari si depasesc tipurile predefinite. Daca
se folosesc implement
ari pe numere mari se obtine punctajul maxim, altfel doar
jumatate din punctaj.
Solutie prezentat
a n GInfo nr. 15/3
Pentru rezolvarea acestei probleme este suficient s
a utiliz
am un sir de biti
care vor indica dac
a un num
ar apare sau nu n fisier.
Vom avea nevoie ntotdeauna de cel mult 250.000 de biti, deci 31250 de octeti.
Initial toti bitii vor avea valoarea 0, iar pe masura ce sunt citite numerele
care formeaz
a matricea, valoarea bitului corespunzator unui num
ar citit devine 1.
S
irul de biti va contine n final o secventa de zerouri care va reprezenta solutia
problemei.
Exist
a si posibilitatea de a utiliza heap-ul pentru a pastra 250.000 de valori
booleene sau ntregi care vor permite si ele determinarea secventei care lipseste.
6.1.2
Rezolvare detaliat
a
6.1.3
Codul surs
a*
6.2. MAXD
139
import java.io.*;
class Numere
{
static byte[] x=new byte[600001];
static int n,min=0,max=0;
public static void main(String[] args) throws IOException
{
int i,j;
long t1,t2;
t1=System.currentTimeMillis();
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(
new FileReader("numere.in")));
st.nextToken(); n=(int)st.nval;
for(i=1;i<=n*n;i++)
{
st.nextToken(); j=(int)st.nval;
if(j<=60000) x[j]=1;
}
min=1;
for(i=1;i<=60000;i++) if(x[i]==0) {min=i; break;}
max=min;
for(i=min+1;i<=60000;i++)
if(x[i]==0) max++; else break;
PrintWriter out=new PrintWriter(
new BufferedWriter(
new FileWriter("numere.out")));
out.println(min+" "+max);
out.close();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}
}
6.2
MaxD
140
maxd.out
200 12 1
maxd.in
2 10
maxd.out
643
Explicatie
200 are 12 divizori iar in intervalul [200, 200]
exist
a un singur num
ar cu aceast
a proprietate
Explicatie
6 este cel mai mic num
ar din interval care are
maxim de divizori egal cu 4 si sunt 3 astfel de
numere 6, 8, 10
6.2.1
Indicatii de rezolvare *
Solutia oficial
a
Pentru un num
ar natural n cuprins n intervalul [a, b], s
a consideram
descompunerea n factori primi:
n = f1e1 f2e2 f3e3 ... fkek
Numarul de divizori ai lui n este dat de formula:
(e1 + 1) (e2 + 1) (e3 + 1) ... (ek + 1)
6.2. MAXD
141
6.2.2
Rezolvare detaliat
a
6.2.3
Codul surs
a*
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
}
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
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
int
int
int
max=-1;
imax=-1;
nrmax=0;
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(...)
143
144
Capitolul 7
Flori
Cristina Bohm
Fetitele din grupa mare de la gr
adinita culeg flori si vor s
a mpleteasc
a
coronite pentru festivitatea de premiere. In gr
adina sunt mai multe tipuri de flori.
Fiecare dintre cele n fetite culege un buchet av
and acelasi num
ar de flori, ns
a nu
neaparat de acelasi tip. Pentru a mpleti coronitele fetitele se mpart n grupe. O
fetita se poate atasa unui grup numai dac
a are cel putin o floare de acelasi tip cu
cel putin o alta fetit
a din grupul respectiv.
Cerint
a
Fiind dat un num
ar natural n reprezent
and num
arul fetitelor si num
arul
natural k reprezent
and num
arul de flori dintr-un buchet, s
a se determine grupele
care se formeaz
a.
Date de intrare
Fisierul de intrare flori.in contine pe prima linie, separate printr-un spatiu,
numerele naturale n si k, reprezent
and num
arul de fetite si respectiv num
arul de
flori din fiecare buchet. Fiecare dintre urmatoarele n linii contine, pentru fiecare
fetita, cate k valori separate prin cate un spatiu reprezent
and tipurile de flori
culese.
Date de iesire
Fisierul de iesire flori.out va contine pe fiecare linie cate o grupa format
a din
numerele de ordine ale fetitelor separate prin cate un spatiu, n ordine cresc
atoare,
ca n exemplu.
Restrictii si preciz
ari
1 n 150
1 k 100
Tipul unei flori este un num
ar ntreg din intervalul [0, 100].
145
146
Intr-o grupa numerele de ordine ale fetitelor trebuie date n ordine strict
crescatoare.
In fisierul de iesire grupele vor fi afisate n ordinea crescatoare a num
arului
de ordine al primei fetite din grupa.
Exemplu
flori.in
54
1234
5696
1111
2443
7777
flori.out
134
2
5
Explicatie
Fetitele 1 si 3 au cules amandou
a flori de tipul 1,
iar fetitele 1 si 4 au cules amandou
a flori de tipurile
2,3 si 4, deci toate cele trei fetite (1, 3, 4) se vor afla
n aceeasi grupa. Fetitele 2 si 5 vor forma fiecare cate
o grupa deoarece nu au cules flori de acelasi tip cu
nici una dintre celelalte fetite.
7.1.1
Indicatii de rezolvare *
Solutia comisiei
- citesc n - num
arul de fetite si k - num
arul de flori dintr-un buchet
- construiesc matricea a definita astfel : pe linia i sunt tipurile distincte de
flori ale fetitei cu num
arul de ordine i
- a[i][0] = num
arul de elemente de pe linia i; acesta va deveni 0 dac
a linia
a fost reunita n alta linie
- vectorul viz are n elemente si pe parcursul prelucrarii , fetitele care ajung
n aceeasi grupa vor avea aceeasi valoare n vectorul viz: de exemplu, dac
a
fetita 3 ajunge n grupa n care e fetita 1 atunci viz[3]=viz[1];
- intial viz[i]=i nsemnand ca fiecare fetita e n grupa doar ea cu ea;
- apelul irelj(i,j) verifica dac
a i e n relatie cu j: cauta pe linia i si j un
tip de floare comun fetitelor i si j
- functia reuneste face reuniunea multimilor de pe liniile i si j n linia i; dac
a
s-a facut o astfel de reuniune, scad i (i ) si astfel se rezolv
a situatia n
care de exemplu i rel j, not ( i rel k) , j rel k; execut
and i--, k
va ajunge tot n grupa cu i; altfel k ar ajunge n alta grupa
- afisarea grupelor presupune selectarea din vectorul viz a pozitiilor care au
aceeasi valoare: toate pozitiile i care au viz[i]=1 (de exemplu) sunt n prima
grupa; pun pe 0 pozitiile afisate pentru a nu le mai relua o data.
7.1. FLORI
7.1.2
Rezolvare detaliat
a
7.1.3
Codul surs
a*
147
Variant
a iterativ
a:
import java.io.*;
class Flori1
{
static int n,k;
static int[][] a=new int[151][101];
static int[] gf=new int[151];
static int[] fgc=new int[101];
public static void main(String[] args) throws IOException
{
int i,j,ii,ng,ok,gasit;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("flori.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("flori.out")));
st.nextToken(); n=(int)st.nval;
st.nextToken(); k=(int)st.nval;
for(i=1;i<=n;i++)
for(j=1;j<=k;j++) { st.nextToken(); a[i][j]=(int)st.nval; }
ng=0;
for(i=1;i<=n;i++)
{
if(gf[i]!=0) continue;
ng++;
for(j=0;j<=100;j++) fgc[j]=0;
for(j=1;j<=k;j++) fgc[a[i][j]]=1;
ok=1;
while(ok==1)
{
ok=0;
for(ii=i+1;ii<=n;ii++)
{
148
out.close();
}// main
}// class
Variant
a recursiva:
import java.io.*;
class Flori2
{
static int n,k,ng;
static char[][] a=new char[151][101];
static int[] gf=new int[151];
public static void main(String[] args) throws IOException
{
int i,j,fij;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("flori.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("flori.out")));
7.1. FLORI
149
st.nextToken(); n=(int)st.nval;
st.nextToken(); k=(int)st.nval;
for(i=1;i<=n;i++)
for(j=1;j<=k;j++) { st.nextToken(); fij=(int)st.nval; a[i][fij]=1;}
ng=0;
for(i=1;i<=n;i++)
{
if(gf[i]!=0) continue;
ng++;
fata(i);
}
for(i=1;i<=ng;i++)
{
for(j=1;j<=n;j++) if(gf[j]==i) out.print(j+" ");
out.println();
}
out.close();
}// main
static void fata(int i)
{
int j,ii;
gf[i]=ng;
for(j=0;j<=100;j++)
{
if(a[i][j]==0) continue;
for(ii=1;ii<=n;ii++)
{
if(ii==i) continue;
if(a[ii][j]==1)
if(gf[ii]==0) fata(ii);
}
}
}// fata(...)
}// class
150
7.2
Pluton
Marinel Serban
In timpul actiunii Furtun
a n desert din cauza unei furtuni de nisip, n
soldati s-au r
at
acit de plutoanele lor. Dup
a trecerea furtunii se pune problema
regruparii acestora pe plutoane. Pentru aceasta se folosesc placutele de identificare
pe care soldatii le poarta la g
at. Pe aceste placute sunt scrise numere care pot
identifica fiecare soldat si plutonul din care acesta face parte. Astfel, soldatii din
acelasi pluton au num
arul de identificare format din aceleasi cifre, dispuse n alta
ordine si numerele de identificare sunt unice. De exemplu, numerele de identificare
78003433, 83043073, 33347008 indic
a faptul ca cei trei soldati care le poarta fac
parte din acelasi pluton.
Cerint
a
Fiind date cele n numere de pe placutele de identificare, s
a se regrupeze cei
n soldati pe plutoane, indic
andu-se num
arul de plutoane g
asite (un pluton refacut
trebuie s
a aib
a minimum un soldat), num
arul de soldati din cel mai numeros
pluton, num
arul de plutoane care au acest num
ar maxim de soldati precum si
componenta unui astfel de pluton (cu num
ar maxim de soldati regrupati).
Date de intrare
Fisierul de intrare pluton.in contine pe prima linie num
arul n de soldati
recuperati, iar pe fiecare dintre urmatoarele n linii cate un num
ar de identificare
a celor n soldati.
Date de iesire
Fisierul de iesire pluton.out va contine pe prima linie num
arul de plutoane
refacute. Linia a doua va contine num
arul de soldati din cel mai numeros pluton
refacut. Linia a treia va contine num
arul de plutoane care au num
arul maxim
de soldati recuperati. Linia a patra va contine componenta unui astfel de pluton,
cu num
ar maxim de soldati recuperati, numerele de identificare ale soldatilor din
componenta fiind scrise unul dupa altul separate prin cate un spatiu.
Restrictii si preciz
ari
0 < n 4000
0 < num
ar de identificare < 2.000.000.000
Observatii
Deoarece linia a patra contine numerele de identificare ale soldatilor unuia
dintre plutoanele cu un num
ar maxim de soldati, pot exista mai multe solutii
corecte. Se poate alege oricare dintre acestea.
Se acorda punctaje partiale 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 cerintelor se
acorda punctajul integral aferent testului.
151
7.2. PLUTON
Exemplu
pluton.in
10
1223
123
666
321
7890
2213
312
655
1000
1322
pluton.out
6
3
2
321 312 123
Explicatie
Au fost recuperati soldati din 6 plutoane
distincte, cei mai multi soldati recuperati
dintr-un pluton fiind n num
ar de 3.
Exist
a 2 plutoane cu num
ar maxim de
soldati recuperati (3), unul dintre ele
fiind format din soldatii cu numerele
321 312 123.
De remarcat ca si solutia
1223 2213 1322 este corecta.
7.2.1
Indicatii de rezolvare *
Solutia comisiei
Solutia 1:
n timpul citirii creez un nou vector care contine pe pozitiile corespunzatoare
numerele de identificare din vectorul initial n ordinea descrescatoare a cifrelor
n etapa a doua se parcurge vectorul nou format grupand toate numerele
de identificare identice; dupa formarea unui grup (pluton) se determin
a marimea
acestuia retinadu-se acesta dac
a e cel mai numeros g
asit pana n acel moment
sau contorizandu-l dac
a num
arul de soldati determinat este egal cu cel maxim
determinat anterior.
Solutia 2:
citesc numerele de identificare n vectorul a[]
construiesc 2 vectori ajut
atori
vectorul b[] care va contine num
arul de cifre al fiecarui element
152
detectez num
arul maxim de elemente ale unui pluton si retin maximul
afisare cerintele 1 2 3 folosind valorile aflate
la cerinta 4
caut in a[] reprezentantul unui pluton numeros
afisez cele maxe elemente - n vectorul sortat elementele cu aceleasi
caracteristici (b si c) sunt unul dupa altul, dar mai trebuie verificat
s
a aib
a caracteristicile reprezentantului (ex. 1212 si 3434 au aceleasi
caracteristici (4,2), (4,2), dar nu fac parte din acelasi pluton)
Solutia 3:
se utilizeaza notiunea de lista: dintr-o lista fac parte toti membrii unui pluton
se construieste un vector ajutator care retine pentru fiecare element elementul care il urmeaza in lista
pe parcursul formarii listelor se determina lista cea mai numeroasa precum
si numarul de liste de acest tip
afisarea se face utilizand informatiile din vetorul urm
7.2.2
Rezolvare detaliat
a
7.2.3
Codul surs
a*
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
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
155
7.2. PLUTON
static
static
static
static
int[]
int[]
int[]
int[]
nip=new int[4001];
z=new int[4001];
fc=new int[10];
x=new int[11];
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
out.println();
out.close();
}// main
}// class
Capitolul 8
8.1
Algoritm
prof. Roxana T
amplaru, Liceul S
tefan Odobleja, Craiova
Georgel scrie un algoritm care contine structuri de atribuire, alternative, de selectie, 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 selectie
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
Nu se face diferent
a ntre literele mari si literele mici. Un algoritm ncepe cu
cuvantul cheie INCEPUT, se termin
a cu SFARSIT si nu contine structuri vide. De
asemenea o structur
a compus
a ncepe cu cuvantul cheie INCEPUT si se termina
cu SFARSIT.
Cerint
a
157
158
Sa se calculeze num
arul minim de date de test necesare pentru verificarea
algoritmului.
Date de intrare:
Din fisierul text ALGOR.IN se citeste algoritmul.
Fisierul contine pe fiecare linie cate un singur cuvant cheie.
Nu exist
a linii vide.
Algoritmul respecta principiile programarii structurate si este scris corect.
Date de iesire:
In fisierul ALGOR.OUT se va scrie pe prima linie num
arul minim de date de
test necesare pentru verificarea algoritmului. Verificarea se bazeaza pe principiul
cutiei transparente, ceea ce nseamna ca testele se compun astfel ncat s
a fie
posibil
a executarea algoritmului pe toate ramurile posibile.
De exemplu, n cazul unei structuri repetitive CAT TIMP care contine n
corpul s
au un singur ATRIB, un test vizeaza o executie far
a s
a se intre n corpul
structurii, altul pentru a trece cel putin o data si prin corpul acestuia.
In mod similar se trateaz
a si structura PENTRU.
Restrictii si preciz
ari
Dup
a cuvintele cheie
ATUNCI, ALTFEL,
CAZ, CAZ IMPLICIT,
CAT TIMP, REPETA, PENTRU
trebuie s
a existe obligatoriu o structur
a de atribuire, alternativ
a, de decizie,
repetitiva sau compus
a.
Exemplul 1:
ALGOR.IN
INCEPUT
atrib
DACA
atunci
ATRIB
SFARSIT
Exemplul 2:
ALGOR.OUT
2
159
8.1. ALGORITM
ALGOR.IN
INCEPUT
ATRIB
REPETA
inceput
atrib
atrib
SFARSIT
pana cand
SFARSIT
ALGOR.OUT
1
OBS.
REPETA se execut
a cel putin o data
ALGOR.OUT
3
OBS.
- se execut
a ATRIB de la primul CAZ
- se execut
a ATRIB de la al doilea CAZ
- nu se execut
a nici primul CAZ,
nici al doilea
Exemplul 3:
ALGOR.IN
INCEPUT
ATRIB
ALEGE
CAZ
ATRIB
CAZ
INCEPUT
ATRIB
ATRIB
SFARSIT
SFARSIT
Exemplul 4:
ALGOR.IN
INCEPUT
ATRIB
ALEGE
CAZ
ATRIB
CAZ
ATRIB
CAZ IMPLICIT
ATRIB
SFARSIT
Exemplul 5:
ALGOR.OUT
3
OBS.
- se execut
a ATRIB
de la primul CAZ
- se execut
a ATRIB
de la al doilea CAZ
- se execut
a ATRIB
de la CAZ IMPLICIT
160
ALGOR.OUT
4
OBS.
- se execut
a ATUNCI si PENTRU
- se execut
a ATUNCI
si nu se execut
a PENTRU
- se execut
a ALTFEL si PENTRU
- se execut
a ALTFEL
si nu se execut
a PENTRU
In total 4 teste.
8.1.1
Indicatii de rezolvare *
8.1.2
Rezolvare detaliat
a*
import java.io.*;
class Algoritm1
{
static String atom;
static String fin="algor.in";
static String fout="algor.out";
static StreamTokenizer st;
static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
static String pauza;
public static void main(String[] args) throws IOException
{
st=new StreamTokenizer(
new BufferedReader( new FileReader(fin)));
st.wordChars((int)_,(int)_);
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter(fout)));
readAtom();
out.println(nrTeste()); // "inceput" bloc
out.close();
8.1. ALGORITM
161
}// main
static int nrTeste() throws IOException
{
int nr, nrTesteAtunci, nrTesteAltfel, nrTesteCaz;
int nrBlocuriDeschise; // inceput
boolean implicit;
String atomr=new String(atom);
System.out.println(" ***> "+atomr);
if(atom.equals("inceput")) // inceput bloc
{
nr=1; // initializare pentru produsul: nr=nr*nrTeste();
nrBlocuriDeschise=1;
readAtom();
while(nrBlocuriDeschise!=0)
{
if(atom.equals("inceput"))
{nrBlocuriDeschise++; readAtom();}
else if(atom.equals("sfarsit")) {nrBlocuriDeschise--; readAtom();}
else nr=nr*nrTeste();
}
}
else if(atom.equals("atrib")) { readAtom(); nr=1; }
else if(atom.equals("daca"))
{
readAtom(); // citeste "atunci"
readAtom(); nrTesteAtunci=nrTeste();
nrTesteAltfel=1;
if(atom.equals("altfel")) {readAtom(); nrTesteAltfel=nrTeste();}
nr=nrTesteAtunci+nrTesteAltfel;
}
else if(atom.equals("alege"))
{
implicit=false;
nr=0;
readAtom();
while(atom.equals("caz")||atom.equals("caz_implicit"))
{
if(atom.equals("caz_implicit")) implicit = true;
readAtom(); nrTesteCaz=nrTeste();
nr=nr+nrTesteCaz;
}
if(!implicit) nr++;
162
}
static void readAtom() throws IOException
{
if(st.nextToken()==StreamTokenizer.TT_EOF) atom="eof";
else atom=st.sval.toString().toLowerCase();
System.out.println("readAtom() "+atom);
pauza=br.readLine();
}
}// class
8.1.3
Codul surs
a*
import java.io.*;
class Algoritm
{
static String atom;
static String fin="algor.in";
static String fout="algor.out";
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
st=new StreamTokenizer(
new BufferedReader(new FileReader(fin)));
st.wordChars((int)_,(int)_);
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter(fout)));
8.1. ALGORITM
163
164
}
static void readAtom() throws IOException
{
if(st.nextToken()==StreamTokenizer.TT_EOF) atom="eof";
else atom=st.sval.toString().toLowerCase();
}
}// class
8.2
Cod de identificare
165
Restrictii si preciz
ari
Codurile sunt formate din cel mult 100 de litere mici ale alfabetului latin.
Exemple:
COD.IN COD.OUT
amaaxm amamax
COD.IN
xmmaaa
COD.OUT
Este ultimul cod.
8.2.1
Indicatii de rezolvare *
Se determin
a cel mai mare indice i pentru care cod[i]<cod[i+1]. Caracterele
de pe ultimile pozitii din cod, incepand cu pozitia i inclusiv, se scriu n noul cod
n ordine crescatoare.
8.2.2
Rezolvare detaliat
a*
O prim
a ncercare ca antrenament cu string-uri!
import java.io.*;
class Cod1
{
static String cod;
static int n;
static int[] nrl=new int[26];
public static void main(String[] args) throws IOException
{
int i;
BufferedReader br=new BufferedReader(new FileReader("cod.in"));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("cod.out")));
cod=br.readLine();
n=cod.length();
System.out.println(cod);
for(i=0;i<n;i++) System.out.print(cod.charAt(i)+"\t ");
System.out.println();
for(i=0;i<n;i++) System.out.print((byte)cod.charAt(i)+"\t ");
System.out.println();
for(i=0;i<n;i++) System.out.print(((byte)cod.charAt(i)-a)+"\t ");
System.out.println();
for(i=0;i<n;i++) nrl[(byte)cod.charAt(i)-a]++;
166
}
}
Totusi, merit
a lucrat cu vector de caractere!
import java.io.*;
class Cod2
{
static char[] cod;
static int n;
static int[] nrl1=new int[26];
static int[] nrl2=new int[26]; // pentru a evita o sortare !
public static void main(String[] args) throws IOException
{
int i,j,k,kk;
BufferedReader br=new BufferedReader(new FileReader("cod.in"));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("cod.out")));
cod=br.readLine().toCharArray();
n=cod.length;
for(k=0;k<n;k++) System.out.print(cod[k]);
System.out.println();
for(i=0;i<n;i++) nrl1[(byte)cod[i]-a]++;
for(i=0;i<26;i++) nrl2[i]=nrl1[i];
i=n-2; // cod[0] ... cod[i] cod[i+1] ... cod[n-2] cod[n-1]
while((i>=0)&&(cod[i]>=cod[i+1]))
{
j=(byte)cod[i+1]-a;
nrl2[j]--;
i--;
}
j=(byte)cod[i+1]-a;
nrl2[j]--;
for(k=0;k<i;k++) System.out.print(cod[k]);
System.out.println();
167
Elimin
and mesajele de urmarire a executiei obtinem versiunea finala.
168
8.2.3
Codul surs
a*
import java.io.*;
class Cod3
{
static char[] cod;
static int n;
static int[] nrl1=new int[26];
static int[] nrl2=new int[26]; // pentru a evita o sortare !
public static void main(String[] args) throws IOException
{
int i,j,k,kk;
BufferedReader br=new BufferedReader(new FileReader("cod.in"));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("cod.out")));
cod=br.readLine().toCharArray();
n=cod.length;
for(i=0;i<n;i++) nrl1[(byte)cod[i]-a]++;
for(i=0;i<26;i++) nrl2[i]=nrl1[i];
i=n-2; // cod[0] ... cod[i] cod[i+1] ... cod[n-2] cod[n-1]
while((i>=0)&&(cod[i]>=cod[i+1]))
{
j=(byte)cod[i+1]-a;
nrl2[j]--;
i--;
}
j=(byte)cod[i+1]-a; // trebuie si el!
nrl2[j]--;
if(i<0) out.println("Este ultimul cod.");
else
{
j=(byte)cod[i]-a; // j = "codul" caracterului cod[i]
nrl2[j]--; // caractere de pus la sfarsit!
for(k=j+1;k<26;k++) // caut primul caracter > cod[i]
if(nrl2[k]<nrl1[k]) // si il pun pe pozitia i
{
cod[i]=(char)(k+a);
nrl2[k]++;
8.3. COMOARA
169
break;
}
i++;
for(k=0;k<26;k++)
if(nrl2[k]<nrl1[k]) // poate lipsi !
for(j=nrl2[k];j<nrl1[k];j++)
{
cod[i]=(char)(k+a);
i++;
}
for(k=0;k<n;k++) out.print(cod[k]);
out.println();
}
out.close();
}
}
8.3
Comoara
170
Datele de iesire:
In fisierul COMOARA.OUT se va afisa valoarea totala a comorilor care pot
fi stranse de cei K membri ai grupului.
Restrictii si preciz
ari
m, n 40, k 10
Exemple
COMOARA.IN
33
0 0 11
14 0 10
19 0 0
5162 4331 1390
5230 1955 9796
5507 6210 1021
000
19 0 0
000
2
32
21
COMOARA.OUT
23909
8.3.1
Indicatii de rezolvare *
171
8.3. COMOARA
8.3.2
Rezolvare detaliat
a
8.3.3
Codul surs
a*
import java.io.*;
class Comoara
{
static int m,n;
static int[][] codCamera;
static int[][] valc;
static int[][] cheiaDinCamera;
static int k;
static int[] lin;
static int[] col;
static
static
static
static
static
boolean[][] traseu;
boolean[][][] amaifost;
boolean[][] arecheia;
int s;
boolean gata;
//
//
//
//
//
//
cod camera
valoare comoara in camera
cheia din camera
nr persoane in grup
linia initiala persoana
coloana initiala persoana
// ce chei are
// suma comorilor
// =true daca nu apar imbunatatiri
172
}
static void rezolvare()
{
int i;
s=0;
for(i=1;i<=k;i++) arecheia[i][0]=true;
for(i=1;i<=k;i++) amaifost[i][lin[i]][col[i]]=true;
gata=false;
while(!gata) alteCautari();
}
static void alteCautari()
{
int i;
gata=true;
for(i=1;i<=k;i++)
{
curatTraseu();
cauta(i,lin[i],col[i]);
}
}
173
8.4. CUBURI
static void curatTraseu()
{
int i,j;
for(i=1;i<=m;i++) for(j=1;j<=n;j++) traseu[i][j]=false;
}
static void cauta(int x, int i, int j)
{
if((i<1)||(i>m)||(j<1)||(j>n)) return;
if(traseu[i][j]) return;
if((!amaifost[x][i][j])&&
(!arecheia[x][codCamera[i][j]])) return;
traseu[i][j]=true;
if(!amaifost[x][i][j]) gata=false;
amaifost[x][i][j]=true;
// face o imbunatatire
arecheia[x][cheiaDinCamera[i][j]]=true;
s=s+valc[i][j];
valc[i][j]=0;
if(arecheia[x][codCamera[i][j]])
{
codCamera[i][j]=0;
cauta(x,i-1,j);
cauta(x,i+1,j);
cauta(x,i,j-1);
cauta(x,i,j+1);
}
}
static void afisare() throws IOException
{
out=new PrintWriter(
new BufferedWriter(new FileWriter("comoara.out")));
out.println(s);
out.close();
}
}
8.4
Cuburi
prof. Ovidiu Domsa, Colegiul Horea, Closca si Crisan, Alba Iulia
174
175
8.4. CUBURI
CUBURI.IN
6
211
324
514
631
463
CUBURI.OUT
0
321
CUBURI.IN
4
211
421
324
CUBURI.OUT
0
0
CUBURI.IN
8
211
514
636
762
324
426
873
CUBURI.OUT
6361
0
CUBURI.IN
8
211
426
324
636
762
516
873
CUBURI.OUT
8732
0
8.4.1
Indicatii de rezolvare *
Identificam pozitia cubului n obiect prin coordonatele sale din (stanga, jos,
fata). De asemenea, pentru ca pe o dimensiune se alipesc cel mult 10 cuburi, folosim
un tablou tridimensional pentru a retine num
arul de ordine al cubului care este
plasat n oricare punct al spatiului n care poate s
a fie construit corpul respectiv.
8.4.2
Rezolvare detaliat
a
8.4.3
Codul surs
a*
import java.io.*;
class Cuburi
{
static int n;
static int[][][] ecubul=new int[21][21][21]; // aici e cubul ...
static int[] x;
// x[i]=coordonata x a cubului i
static int[] y;
// y[i]=coordonata y a cubului i
static int[] z;
// z[i]=coordonata z a cubului i
static boolean[] eplasat;
static int minx, maxx, miny, maxy, minz, maxz; // coordonate obiect
176
177
8.5. FIBO
case sus:
case jos:
case stanga:
case dreapta:
case fata:
case spate:
default:
}
if(ecubul[x[cubnou]][y[cubnou]][z[cubnou]]!=0)// fata ocupata
{
out.println(cubnou+" "+cubvechi+" "+fatacubvechi+" 2");
out.println("0");
// succesiunea nu e valida
ok=false;
break;
// iese din for ==> nu mai pun "else" !
}
ecubul[x[cubnou]][y[cubnou]][z[cubnou]]=cubnou;
eplasat[cubnou]=true;
}
if(ok)
if((maxx-minx+1)*(maxy-miny+1)*(maxz-minz+1)==n)
{
out.println("0");
out.println((maxz-minz+1)+" "+(maxx-minx+1)+" "+(maxy-miny+1));
}
else
{
out.println("0");
out.println("0");
}
out.close();
}
}
8.5
Fibo
prof. Marinel S
erban, Liceul de Informatic
a, Iasi
Consider
am sirul lui Fibonacci: 0, 1, 1, 2, 3, 5, 8, 13, 21, ...
Dat fiind un num
ar natural (n N), scrieti acest num
ar sub forma de suma
de elemente neconsecutive din sirul Fibonacci, fiecare element put
and s
a apar
a cel
mult o data, astfel ncat num
arul de termeni ai sumei s
a fie minim.
Date de intrare
Din fisierul FIB.IN se citeste de pe prima linie num
arul natural n.
178
Datele de iesire
In fisierul de iesire FIB.OUT se vor afisa termeni ai sirului Fibonacci, cate
unul pe linie, a caror sum
a este n.
Restrictii si preciz
ari
n poate avea maxim 80 de cifre
Exemple:
FIB.IN FIB.OUT
20
2
5
13
FIB.IN
8
FIB.OUT
8
8.5.1
Indicatii de rezolvare *
Se determin
a cel mai mare num
ar din sirul Fibonacci care este mai mic
sau egal cu num
arul dat. Acesta este primul num
ar din solutie. Se determin
a cel
mai mare num
ar din sirul Fibonacci care este mai mic sau egal cu diferenta dintre
num
arul dat si primul num
ar din solutie. Acesta este al doilea num
ar din solutie. Se
repeta acest algoritm pana cand num
arul r
amas devine zero. Se folosesc operatiile
de adunare, sc
adere si comparare cu numere mari.
8.5.2
Rezolvare detaliat
a
8.5.3
Codul surs
a*
import java.io.*;
class Fibo
{
static int nf=385; // 81 cifre Fibo
static int[][] f=new int[nf+1][1];
static int[] x;
static PrintWriter out;
public static void main(String[] args) throws IOException
{
int k,i,iy,y;
BufferedReader br=new BufferedReader(new FileReader("fib.in"));
out=new PrintWriter(new BufferedWriter(new FileWriter("fib.out")));
8.5. FIBO
char[] a=br.readLine().toCharArray();
int nx=a.length;
x=new int[nx];
for(i=0;i<a.length;i++) x[nx-1-i]=a[i]-0;
f[0]=nr2v(0);
f[1]=nr2v(1);
f[2]=nr2v(1);
for(k=3;k<=nf;k++) f[k]=suma(f[k-1],f[k-2]);
while(compar(x,nr2v(0))>0)
{
iy=maxFibo(x);
afisv(f[iy]);
x=scade(x,f[iy]);
}
out.close();
}
static int maxFibo(int[] nr)
{
int k;
for(k=1;k<=nf;k++) if (compar(f[k],nr)>0) break;
return k-1;
}
static int compar(int[] a, int[] b) //-1, 0, 1 ... a < = > b
{
int na=a.length;
int nb=b.length;
if(na>nb) return 1; else if(na<nb) return -1;
int i=na-1;
while((i>=0)&&(a[i]==b[i])) i--;
if(i==-1) return 0;
else if(a[i]>b[i]) return 1; else return -1;
}
static int[] scade(int[] x,int[] y) // z=x-y unde x>=y
{
int nx=x.length;
int ny=y.length;
int nz=nx;
179
180
}
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;
8.6. KOMMANDO
181
}
}
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 void afisv(int[] x)
{
int i;
for(i=x.length-1;i>=0;i--) out.print(x[i]);
out.println();
}
}
8.6
Kommando
prof. Marinel S
erban, Liceul de Informatic
a, Iasi
Intr-o cl
adire cu h etaje sunt detinuti, la parter, cativa prizonieri de
catre T teroristi. Fiecare etaj al cladirii are m n camere identice. Fiecare camera
are un cod numeric (nu neap
arat 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 fiecare membru al trupei a aterizat
pe acoperis.
Greutatea fiec
arui membru al trupei este exprimat
a n unitati 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 definitii.
Definitie: 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
182
n
c112
h
...
K
c11n
T
c121
c122
...
c12n
...
c1m1 ...
c1mn
ch12
x1
...
y1
ch1n
ch21
ch22
...
ch2n
...
chm1 ...
chmn
xK
yK
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.
Restrictii si preciz
ari
2 m, n, h 35
1 xi m
1 T, K, Gi 255
0 cijk 255
Toate valorile sunt ntregi.
Exemplu:
1 yi n
183
8.6. KOMMANDO
KOMMANDO.IN
55532
0 0 0 0 0 0 0 33 0 0 0
00000 01 0000
0 0 0 0 0 11 0 0 0 0 0
00000 00 0000
00000 00 0000
122
233
344
02 0000030 00000
44 2 0 0 0 0 0 3 0 0 0 0 0 0
0 2 22 0 0 0 0 0 3 0 0 0 0 0
66 2 0 0 0 0 0 7 0 15 0 0 0 0
00 0000000 00000
KOMMANDO.OUT
DA
2
8.6.1
Indicatii de rezolvare *
8.6.2
Rezolvare detaliat
a
8.6.3
Codul surs
a*
184
}
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;
8.6. KOMMANDO
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
185
186
static
static
static
static
static
static
int[] xk;
int[] yk;
int[] G;
int ns=0;
boolean aajunslaparter;
boolean[][][] traseu;
//
//
//
//
x acoperis soldat k
y acoperis soldat k
greutatea
nr soldati ajunsi la parter
8.6. KOMMANDO
{
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++)
187
188
}
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;
8.6. KOMMANDO
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;
}
}
189
190
8.6. KOMMANDO
191
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");
}
192
8.6. KOMMANDO
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;
193
194
}
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 9
Ferma
196
(far
a s
a fie separate prin spatii) av
and semnificatia:
. - teren neacoperit de robot;
* - teren ce poate fi verificat de robot;
+ - loc n care a r
amas copacul.
Restrictii
1 N, M 50
Exemplu
FERMA.IN
12 11
. .
.
.
. .
.
+
. .
.
.
. .
.
.
. .
.
.
. .
.
+
. + .
.
. .
.
.
. .
+ .
. .
.
.
. .
.
.
. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
FERMA.OUT
. .
.
.
. .
.
+
. .
* *
. .
* *
. + * *
. .
.
+
. + .
*
. .
.
*
. .
+ *
* * * *
* * * *
* * * *
*
*
*
*
*
*
*
*
*
*
*
*
.
.
.
.
.
.
R
.
.
.
.
.
.
.
.
.
.
.
.
.
.
+
.
+
.
.
.
.
.
.
.
.
.
.
.
.
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
+
.
+
*
*
*
*
*
*
*
*
*
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
+
.
.
.
.
.
+
.
.
.
.
*
*
*
*
*
*
*
*
*
.
.
.
.
+
*
*
*
*
*
+
.
.
.
.
.
.
.
.
.
.
.
.
+
.
.
.
.
.
*
*
*
*
*
.
+
.
.
.
9.1.1
Indicatii de rezolvare *
9.1. FERMA
9.1.2
197
Rezolvare detaliat
a*
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++)
{
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();
}
}
198
9.1.3
Codul surs
a*
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
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))
9.1. FERMA
199
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
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();
}
}
200
9.2
Fractii
1/1
1/2
2/1
1/1
1/2
1/3
2/1
3/2
2/3
3/1
Cerint
a
Dandu-se o fractie oarecare prin num
ar
atorul si numitorul s
au, determinati
num
arul nivelului pe care se afla fractia sau o fractie echivalent
a (av
and aceeasi
valoare) cu aceasta.
Date de intrare
Fisier de intrare: FRACTII.IN
Linia 1: N M - dou
a numere naturale nenule, separate printr-un spatiu,
reprezent
and num
ar
atorul si numitorul unei fractii.
Date de iesire
Fisier de iesire: FRACTII.OUT
Linia 1: niv - num
ar natural nenul, reprezent
and num
arul nivelului care
corespunde fractiei.
Restrictii
1 < N, M 2.000.000.000
Exemple
FRACTII.IN
13 8
FRACTII.OUT
6
FRACTII.IN
12 8
FRACTII.OUT
3
9.2.1
Indicatii de rezolvare *
9.2. FRACT
II
9.2.2
Rezolvare detaliat
a
9.2.3
Codul surs
a*
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;
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;
}
}
201
202
9.3
Tablou
TABLOU.OUT
4 6 7
7 4 5
5 7 6
9.3.1
Indicatii de rezolvare *
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 fiecare linie si fiecare coloana
203
9.3. TABLOU
9.3.2
Rezolvare detaliat
a*
import java.io.*;
class Tablou1
{
static int n,s,x,sp,p;
static int[][] a;
//
//
//
//
204
}
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();
}
}
}
9.3.3
Codul surs
a*
import java.io.*;
class Tablou2
{
static int n,s,x,sp,p;
static int[][] a;
//
//
//
//
9.4. COMPETIT
IE DIFICILA
205
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]+" ");
out.println();
}
out.close();
}
}
9.4
Competitie dificil
a
206
Date de intrare
Fisier de intrare: COMPET.IN
Linia 1: N M - dou
a numere naturale nenule, reprezent
and num
arul concurentilor,
respectiv num
arul relatiilor pe care si le aminteste comisia;
Liniile 2..M+1: i j - pe fiecare din aceste M linii se afla cate dou
a numere
naturale nenule i si j, av
and semnificatia: 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: nr1 nr2 ... nrN - pe aceast
a linie se va scrie clasamentul sub forma
unui sir de numere naturale nenule, separate prin cate un spatiu, reprezent
and
numerele de concurs ale concurentilor, n ordine de la primul clasat la ultimul.
Restrictii si preciz
ari
1 < N 1000
se garanteaza corectitudinea datelor de intrare si faptul ca exista totdeauna
o solutie.
Exemple
COMPET.IN
31
12
COMPET.OUT
123
COMPET.IN
42
21
34
COMPET.OUT
2134
9.4.1
Indicatii de rezolvare *
9.4.2
Rezolvare detaliat
a
9.4.3
Codul surs
a*
import java.io.*;
9.4. COMPETIT
IE DIFICILA
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];
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]]--;
}
207
208
9.5
Cuvinte
209
9.5. CUVINTE
Exemple
CUVINTE.IN
715
car
cer
cerc
mar
mare
rosu
inrosit
CUVINTE.OUT
2
car
mar
mare
CUVINTE.IN
716
car
cer
cerc
mar
mare
rosu
inrosit
CUVINTE.OUT
0
9.5.1
Indicatii de rezolvare *
9.5.2
Rezolvare detaliat
a
9.5.3
Codul surs
a*
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;
210
}
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;
9.6. GRUP
211
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;
}
}
}
}
9.6
Grup
212
Cerint
a
Dandu-se o mpartire n grupe a celor N calculatoare, determinati cele dou
a
variante candidate pentru mpartirea 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 retea si num
arul (k) de grupe.
Linia 2: g1 g2 . . . gk - num
arul calculatoarelor din fiecare grupa.
Date de iesire
Fisier de iesire: GRUP.OUT
p - num
arul de grupe din mpartirea care precede lexicografic imediat
mpartirea data;
h1 h2 ... hp - num
arul de calculatoare din cele p grupe ale mpartirii precedente;
u - num
arul de grupe din mpartirea care succede lexicografic imediat
mpartirea data;
t1 t2 ... tu - num
arul de calculatoare din cele u grupe ale mpartirii urmatoare;
Restrictii si preciz
ari
2 N 1000
g1 + g2 + ... + gk = h1 + h2 + ... + hp = t1 + t2 + ... + tu = N
1 g1 g2 ... gk ; 1 h1 h2 ... hp ; 1 t1 t2 ... tu ;
1<k<N
1 p, u N
Exemplu
GRUP.IN
14 3
266
GRUP.OUT
3
257
2
2 12
9.6.1
Indicatii de rezolvare *
9.6. GRUP
213
jumatate se plaseaz
a pe pozitia k + 1 (daca g[k] este impar, grupul de pe pozitia
k + 1 va avea cu un calculator mai mult decat grupul de pe pozitia 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]. Secventa va avea i + 1 grupe. Primele i 1 grupe de calculatoare
r
aman neschimbate. Pe pozitia i plas
am g[i] 1 calculatoare iar pe pozitia i + 1
restul calculatoarelor.
Pentru secventa urmatoare (lexicografic):
Daca g[k 1] + 1 > g[k] 1 atunci secventa are k 1 grupe. Primele k 2
grupe r
aman neschimbate iar pe pozitia k 1 se pun mpreuna calculatoarele de
pe pozitiile k 1 si k (din secventa initiala).
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 secventa initiala) se vor distribui n
grupuri de g[k 1] + 1 calculatoare (cu exceptia ultimului grup, eventual, care va
avea cel putin g[k1]+1 calculatoare dar nu mai mult de 2g[k1]+1 calculatoare).
9.6.2
Rezolvare detaliat
a
9.6.3
Codul surs
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
214
}
}
Capitolul 10
Pentagon
216
PENTAGON.OUT
17
21
32
51
10.1.1
Indicatii de rezolvare *
Solutie prezentat
a n GInfo 12/6
Rezolvarea acestei probleme este foarte simpla, ea neimplic
and decat parcurgerea pe coloane a unei matrice, contorizarea unor secvente de zerouri si pastrarea
unei statistici referitoare la aceste secvente.
Pentru a determina blocurile necesare, vom determina blocurile pe fiecare
coloana (datorit
a faptului ca l
atimea unui bloc este ntotdeauna 1 si toate blocurile
sunt dispuse pe verticala, un bloc poate ocupa o singur
a coloana).
Pentru a determina blocurile de pe o coloana va trebui s
a determin
am secventele
de zerouri de pe coloana respectiv
a. Vom lua n considerare doar secventele de
lungime maxima pentru a minimiza num
arul total de blocuri. De exemplu, dac
a
avem sase zerouri consecutive, am putea folosi un bloc de lungime 6, dar si dou
a
blocuri de lungime 5 si 1, 4 si 2 etc. Evident, este obligatoriu s
a folosim un singur
bloc pentru ca num
arul total al blocurilor utilizate s
a fie minim.
Asadar, pentru fiecare coloana vom determina lungimile secventelor de zerouri. O secvent
a de zerouri poate ncepe fie pe prima linie a coloanei, fie n momentul
n care nt
alnim o linie pe care se afla un element cu valoarea 0 n timp ce pe linia
anterioar
a se afla un element cu valoarea 1. Secventa se va termina fie la terminarea
parcurgerii coloanei (se ajunge pe ultima linie a acesteia), fie n momentul n
care nt
alnim o linie pe care se afla un element cu valoarea 1 n timp ce pe linia
anterioar
a se afla un element cu valoarea 0.
In momentul detect
arii termin
arii unei secvente (presupunem ca lungimea
acesteia este x), num
arul blocurilor de lungime x este incrementat. Pentru pastrarea
num
arului de blocuri se utilizeaza un sir a, unde ax indic
a num
arul blocurilor de
lungime x.
10.1. PENTAGON
217
La sfarsit, vom afisa statistica ceruta pe baza datelor pastrate n sirul a. Vor
fi afisate toate perechile de forma i ai care respecta conditia ai 6= 0.
Analiza complexit
atii
Datorit
a faptului ca num
arul de elemente care compun o secventa de zerouri
poate fi determinat pe masura ce este parcurs
a secventa, ntregul algoritm const
a
ntr-o singur
a traversare a matricei. Ordinul de complexitate al unei astfel de
traversari este O(m n), unde m reprezint
a num
arul de linii ale matricei, iar n
reprezint
a num
arul de coloane.
Pentru citirea datelor, matricea este parcurs
a o singur
a data, deci ordinul de
complexitate al acestei operatii este tot O(m n).
Pentru afisarea datelor se parcurge o singur
a data sirul a; acesta nu poate
contine mai mult de m elemente deoarece nu pot fi folosite blocuri mai nalte decat
naltimea zidului. Asadar, scrierea solutiei are ordinul de complexitate O(m).
In concluzie, ordinul de complexitate al algoritmului de rezolvare a acestei
probleme este O(m n) + O(m n) + O(m) = O(m n).
10.1.2
Rezolvare detaliat
a
10.1.3
Codul surs
a*
import java.io.*;
class Pentagon
{
static int m,n;
static String[] a;
static int[] f;
public static void main(String[]args) throws IOException
{
int i,j,k;
BufferedReader br=new BufferedReader(new FileReader("pentagon.in"));
StreamTokenizer st=new StreamTokenizer(br);
st.nextToken();m=(int)st.nval;
st.nextToken();n=(int)st.nval;
a=new String[m];
f=new int[n+1]; // frecventa lungimilor blocurilor
br.readLine(); // altfel nu merge !!!
218
for(i=0;i<m;i++) a[i]=br.readLine();
for(j=0;j<n;j++)
{
i=0;
while(i<m)
{
while((i<m)&&(a[i].charAt(j)==1)) i++;
k=0;
while((i<m)&&(a[i].charAt(j)==0)) {k++; i++;}
f[k]++;
}
}
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("pentagon.out")));
for(k=1;k<=n;k++) if(f[k]>0) out.println(k+" "+f[k]);
out.close();
}
}
10.2
Pod
prof. Marinel S
erban, Iasi
Intre dou
a maluri ale unei v
ai adanci s-a construit un pod suspendat
format din N bucati 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 aflam.
In timp unele bucati de sc
andur
a s-au deteriorat, iar altele chiar au disparut.
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:
Scrieti un program care s
a determine num
arul de modalit
ati de traversare a
podului (mai exact, de a ajunge pe celalalt mal), precum si o solutie de traversare,
dac
a o astfel de solutie exist
a.
Date de intrare:
Fisierul de intrare POD.IN are structura:
219
10.2. POD
POD.IN
N
k s1 s2 ... sk
h d1 d2 ... dh
Semnificatie
Numarul total de sc
anduri
Numarul de sc
anduri lipsa si numerele lor de ordine
Numarul de sc
anduri deteriorate si numerele lor de ordine
Date de iesire:
Fisierul de iesire POD.OUT va contine pe prima linie valoarea -1 dac
a nu
este posibil s
a traversam podul, respectiv num
arul de posibilitati de a traversa
podul, dac
a aceasta este posibil.
In cazul n care exist
a solutii, pe cea de a doua linie va fi afisata o astfel de
solutie, prin indicarea, n ordine, a sc
andurilor pe care se paseste, sub forma:
POD.OUT
Nr
p1 p2 ... pm
Semnificatie
Numarul total de posibilitati
Solutia determinata, prin indicarea n ordine a sc
andurilor
pe care se paseste
Restrictii si preciz
ari:
3 N 300
0 k, h N
{s1 , s2 , ..., sk } {2, ...N },
{d1 , d2 , ..., dh } {1, 2, ...N };
{s1 , s2 , ..., sk } {d1 , d2 , ..., dh } =
N r are cel mult 80 de cifre.
Exemple:
pod.in pod.out
5
24
0
3
0
pod.in
10
227
15
pod.out
48
368
pod.in
6
224
13
pod.out
-1
10.2.1
Indicatii de rezolvare *
Solutie 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 posibilitati de a ajunge pe cea
de-a i-a sc
andur
a depinde doar de num
arul de posibilitati de a ajunge pe cele trei
sc
anduri aflate n fata ei.
Vom nota cu ti num
arul de posibilitati de a ajunge pe cea de-a i-a sc
andur
a.
Vom considera malul opus ca fiind cea de-a (N + 1)-a sc
andur
a, unde N este
num
arul sc
andurilor care formeaz
a podul.
Solutia problemei va fi data de valoarea tN +1 .
220
10.2. POD
221
Datorit
a faptului ca vor fi cel mult N astfel de determin
ari, ordinul de complexitate al operatiei de determinare a modalit
atii de traversare este O(N ). Scrierea
num
arului posibilitatilor de traversare poate fi considerat a fi o operatie elementara, deci are ordinul de complexitate O(1). Asadar, ordinul de complexitate al
operatiei de scriere a datelor de iesire este O(N) + O(1) = O(N).
In concluzie, algoritmul de rezolvare al acestei probleme are ordinul de complexitate O(N ) + O(N ) + O(N ) + O(N ) = O(N ).
10.2.2
Rezolvare detaliat
a*
import java.io.*;
class Pod1
{
static final int buna=0, deteriorata=1, lipsa=2;
static int ns, nsl,nsd;
static int nsol;
static int[] x;
static int[] y;
static int[] p;
public static void main(String[] args) throws IOException
{
int i,j;
StreamTokenizer st=new StreamTokenizer(new BufferedReader(
new FileReader("pod.in")));
PrintWriter out=new PrintWriter(new BufferedWriter(
new FileWriter("pod.out")));
st.nextToken(); ns=(int)st.nval;
x=new int[ns+2];
y=new int[ns+2]; // nsol[i] ajunge in i
p=new int[ns+2]; // predecesor
st.nextToken();nsl=(int)st.nval; // lipsa
for(i=1;i<=nsl;i++)
{
st.nextToken(); j=(int)st.nval;
x[j]=lipsa;
}
st.nextToken();nsd=(int)st.nval; // deteriorate
for(i=1;i<=nsd;i++)
222
pas din 2
pasi din 1
// 3 pasi de pe mal;
// 2 pasi din 1
// 1 pas din 2
for(i=4;i<=ns+1;i++)
{
switch(x[i])
{
case lipsa:
y[i]=0; break;
case deteriorata:
if(x[i-1]!=lipsa) y[i]=y[i-1]; // 1 pas
break;
case buna:
y[i]=0;
// pentru
if(x[i-3]==buna) y[i]+=y[i-3]; // 3 pasi
if(x[i-2]==buna) y[i]+=y[i-2]; // 2 pasi
din i-1
suma
din i-3
din i-2
223
10.2. POD
if(x[i-1]!=lipsa) y[i]+=y[i-1]; // 1 pas
din i-1
}
afisv(y);
}
}// main
static void afisv(int[] a)
{
int i;
for(i=1;i<=ns+1;i++) System.out.print(a[i]+" ");
System.out.println();
}
}// class
import java.io.*;
class Pod2
{
static final int buna=0, deteriorata=1, lipsa=2;
static int ns, nsl,nsd;
static int nsol;
static int[] x;
static int[] y;
static int[] p;
public static void main(String[] args) throws IOException
{
int i,j;
StreamTokenizer st=new StreamTokenizer(new BufferedReader(
new FileReader("pod.in")));
PrintWriter out=new PrintWriter(new BufferedWriter(
new FileWriter("pod.out")));
st.nextToken();ns=(int)st.nval;
x=new int[ns+2];
y=new int[ns+2]; // nsol[i] ajunge in i
p=new int[ns+2]; // predecesor
st.nextToken();nsl=(int)st.nval; // lipsa
for(i=1;i<=nsl;i++)
{
st.nextToken(); j=(int)st.nval;
x[j]=lipsa;
}
224
10.2. POD
break;
case buna:
y[i]=0;
// pentru suma
if(x[i-3]==buna) y[i]+=y[i-3]; // 3 pasi din i-3
if(x[i-2]==buna) y[i]+=y[i-2]; // 2 pasi din i-2
if(x[i-1]!=lipsa) y[i]+=y[i-1]; // 1 pas din i-1
if(y[i-3]>0) p[i]=i-3;
else if(y[i-2]>0) p[i]=i-2;
else if(y[i-1]>0) p[i]=i-1;
}
afisv(y);
}
System.out.println();
drum(ns+1);
System.out.println();
}// main
static void drum(int j)
{
if(p[j]!=0) drum(p[j]);
System.out.print(j+" ");
}
static void afisv(int[] a)
{
int i;
for(i=1;i<=ns+1;i++) System.out.print(a[i]+" ");
System.out.println();
}
}// class
10.2.3
Codul surs
a*
import java.io.*;
class Pod3
{
static final int buna=0, deteriorata=1, lipsa=2;
static int ns, nsl,nsd;
static int nsol;
static int[] x; // tip scandura
static int[][] y; // y[i]=nr variante de a ajunge in i
225
226
10.2. POD
227
else if(x[3]==buna)
{
y[3]=suma(y[3],nrv(1));
// 3 pasi de pe mal;
if(x[1]==buna) y[3]=suma(y[3],y[1]); // 2 pasi din 1
if(x[2]!=lipsa) y[3]=suma(y[3],y[2]); // 1 pas din 2
}
if(ok(y[1])) p[3]=1;
else if(ok(y[2])) p[3]=2;
for(i=4;i<=ns+1;i++)
{
switch(x[i])
{
case lipsa:
y[i]=nrv(0); break;
case deteriorata:
if(x[i-1]!=lipsa) y[i]=suma(nrv(0),y[i-1]);// 1 pas din i-1
if(ok(y[i-1])) p[i]=i-1;
break;
case buna:
y[i]=nrv(0); // pentru suma
if(x[i-3]==buna) y[i]=suma(y[i],y[i-3]); // 3 pasi din i-3
if(x[i-2]==buna) y[i]=suma(y[i],y[i-2]); // 2 pasi din i-2
if(x[i-1]!=lipsa) y[i]=suma(y[i],y[i-1]); // 1 pas din i-1
if(ok(y[i-3])) p[i]=i-3;
else if(ok(y[i-2])) p[i]=i-2;
else if(ok(y[i-1])) p[i]=i-1;
}
}
afisv(y[ns+1]);
drum(ns+1);
out.println();
out.close();
}// main
static boolean ok(int[] z)
{
int i;
for(i=0;i<z.length;i++) if(z[i]!=0) return true;
return false;
}
static void drum(int j)
228
{
if(p[j]!=0) drum(p[j]);
out.print(j+" ");
}
static void afisv(int[] x)
{
int nx=x.length;
int i;
for(i=nx-1;i>=0;i--) out.print(x[i]);
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[] 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;
10.3. SUMA
229
else
{
int[] zz=new int[nz-1];
for(k=0;k<nz-1;k++) zz[k]=z[k];
return zz;
}
}
}// class
10.3
Suma
SUMA.OUT
7
1
7
Deci suma 12 se poate obtine din minimum 7 termeni astfel:
12 = 1 + 2 + 3 + 4 + 5 + 6 7.
230
10.3.1
Indicatii de rezolvare *
Solutie prezentat
a n GInfo 12/6
Pentru ca num
arul termenilor s
a fie minim, trebuie ca suma termenilor care
apar cu semn negativ s
a fie cat mai mica posibil.
Initial vom presupune ca nu va trebui s
a sc
adem nici o valoare si ne propunem
s
a g
asim cel mai mic num
ar N pentru care
PN
sN = i=1 i S.
Valoarea N se obtine rezolv
and ecuatia de gradul II SN = S (vom avea
SN S + N ) si rotunjind prin adaos r
adacina pozitiva obt
inuta. Avem:
N (N +1)
1+8S1
2
=
S
N
+
N
S
=
0
N
=
2
2
l
m
1+8S1
.
Datorit
a
faptului
ca N este cea mai
Asadar, valoarea N este
2
mica valoare pentru care suma atinge sau depaseste valoarea S, solutia problemei
nu poate fi data de nici un num
ar N < N .
In cele ce urmeaz
a vom demonstra ca solutia problemei este data de N , N +1
sau N + 2. Se observa ca numerele SN , SN +1 si SN +2 nu pot avea toate aceeasi
paritate, deoarece N + 1 si N + 2 au paritati diferite. Vom nota prin DN diferenta
dintre valoarea SN si valoarea care trebuie obtinuta (S). Deoarece se scade aceeasi
valoare din SN , SN +1 si SN +2 este evident ca DN , DN +1 si DN +2 nu pot avea
toate aceeasi paritate.
Solutia problemei este data de indicele celui mai mic num
ar par dintre aceste
trei numere; fie acest indice N .
Suma totala a elementelor carora trebuie s
a le fie modificat semnul este
DN /2. Prin modificarea semnului unui element, valoarea expresiei scade cu dublul
acestui element, deci avem SN DN /2 2 = S.
azute). Deoarece
Fie x = DN /2 (suma totala a elementelor care trebuie sc
N < N + 2, obtinem SN SN + N + 1 + N + 2. Folosind relatia SN S + N ,
10.3. SUMA
231
10.3.2
Rezolvare detaliat
a
10.3.3
Codul surs
a*
import java.io.*;
class Suma
{
public static void main(String[] args) throws IOException
{
int n=0,suma=0,s;
int np;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("suma.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("suma.out")));
st.nextToken(); s=(int)st.nval;
while((suma<s)||((suma-s)%2==1))
{
n++;
suma=suma+n;
}
out.println(n);
np=(suma-s)/2;
if(np>0)
if(np<=n) out.println(np);
else out.println((np-n)+"\n"+n);
out.close();
}
}
232
10.4
Becuri
prof. Cristina B
arbieru, Timisoara
Un panou publicitar, de forma dreptunghiulara contine becuri, unul
l
anga altul, aliniate pe linii si coloane.
Fiecare linie si fiecare coloana are un comutator care schimba starea tuturor
becurilor de pe acea linie sau coloana, din starea n care se afla n starea opusa
(stins/aprins, aprins/stins). Asupra unui bec nu se poate actiona individual. Initial
panoul are toate becurile stinse.
Cerint
a:
Sa se realizeze un program care act ionand asupra unui num
ar minim de linii
si coloane aduce panoul din starea initiala, la o configuratie data, dac
a acest lucru
este posibil.
Datele de intrare
se vor citi din fisierul BECURI.IN, care are urmatoarea configuratie:
pe prima linie dou
a numere naturale, m si n, separate prin spatiu, reprezent
and num
arul de linii si de coloane ale panoului;
pe urmatoarele m linii cate n coloane, formate din elementele 0 sau 1, separate prin spatiu, reprezent
and configuratia finala a panoului. 1 este codificarea
unui bec aprins iar 0 a unui bec stins.
Datele de iesire
se va afisa o solutie n fisierul BECURI.OUT astfel:
pe prima linie a fisierului indicii coloanelor asupra carora s-a actionat,
separati prin spatiu.
pe a doua linie a fisierului indicii linilor asupra carora s-a actionat, separati
prin spatiu.
Daca nu se actioneaz
a asupra liniilor sau coloanelor se va afisa 0 pe linia
corespunzatoare.
Numerotarea liniilor, respectiv coloanelor ncepe de la 1.
Daca problema nu are solutie, pe prima linie a fisierului se va afisa 1.
Restrictii
m 100, n 100
Exemplu:
BECURI.IN
56
101101
101101
101101
010010
010010
BECURI.OUT
25
123
10.4. BECURI
10.4.1
233
Indicatii de rezolvare *
Solutie prezentat
a n GInfo 12/6
Este evident ca pentru a obtine prima linie a matricei nu putem decat fie
s
a comutam toate coloanele pe care trebuie s
a se afle becuri aprinse si s
a nu
comutam prima linie, fie s
a comutam prima linie si s
a comutam toate coloanele pe
care trebuie s
a se afle becuri stinse.
Analog, pentru prima coloana putem fie s
a comutam toate liniile pe care
trebuie s
a se afle becuri aprinse si s
a nu comutam prima coloana, fie s
a comutam
prima coloana si s
a comutam toate liniile pe care trebuie s
a se afle becuri stinse.
Astfel avem patru posibilitati de a obtine configuratia ceruta:
comutam liniile carora le corespund becuri aprinse pe prima coloana si
coloanele carora le corespund becuri aprinse pe prima linie;
comutam liniile carora le corespund becuri aprinse pe prima coloana si
coloanele carora le corespund becuri stinse prima linie;
comutam liniile carora le corespund becuri stinse pe prima coloana si
coloanele carora le corespund becuri aprinse pe prima linie;
comutam liniile carora le corespund becuri stinse pe prima coloana si
coloanele carora le corespund becuri stinse pe prima linie.
Vom verifica fiecare dintre aceste patru variante si apoi o vom alege pe cea
care implica cele mai putine comutari de linii si coloane.
Daca nici una dintre cele patru variante nu duce la obtinerea configuratiei
cerute, putem trage concluzia ca aceasta nu poate fi obtinuta prin comutarea unor
linii si a unor coloane.
Analiza complexit
atii
Citirea datelor de intrare implic
a parcurgerea unei matrice patratice, deci
ordinul de complexitate al acestei operatii este O(N 2 ).
Verificarea fiec
areia dintre cele patru posibilitati de a obtine solutia implica
parcurgerea primei linii si a primei coloane; ordinul de complexitate al unei astfel
de parcurgere este O(N ) + O(N ) = O(N ).
Pentru fiecare element este posibil ca linia/coloana corespunzatoare s
a fie
comutat
a. Operatia de comutare implic
a traversarea liniei sau coloanei, asadar are
ordinul de complexitate O(N ). Ca urmare, ordinul de complexitate al fiecareia
dintre cele patru posibilitati este O(N ) O(N ) = O(N 2 ). Intreaga operatie de
determinare a solutiei are ordinul de complexitate 4 O(N 2 ) = O(N 2 ).
Scrierea datelor de iesire implic
a traversarea sirurilor care indic
a dac
a o linie
sau coloana a fost comutat
a; ordinul de complexitate al operatiei este O(N ).
In concluzie, algoritmul de rezolvare al acestei probleme are ordinul de complexitate O(N 2 ) + O(N 2 ) + O(N ) = O(N 2 ).
10.4.2
Rezolvare detaliat
a*
Prima faz
a: pun zero pe prima linie si verific.
234
import java.io.*;
class Becuri1
{
static int m,n;
static byte[][] a;
static byte[][] b;
static byte[] colc;
static byte[] linc;
static byte[] colcsol;
static byte[] lincsol;
static int ncolcsol=234, nlincsol=234;
public static void main(String[]args) throws IOException
{
int i,j,k;
BufferedReader br=new BufferedReader(new FileReader("becuri.in"));
StreamTokenizer st=new StreamTokenizer(br);
st.nextToken(); m=(int)st.nval;
st.nextToken(); n=(int)st.nval;
a=new byte[m+1][n+1];
b=new byte[m+1][n+1];
colc=new byte[n+1];
colcsol=new byte[n+1];
linc=new byte[m+1];
lincsol=new byte[m+1];
for(i=1;i<=m;i++)
for(j=1;j<=n;j++)
{ st.nextToken(); a[i][j]=(byte)st.nval; }
fac0Linia1();
// .... fac1Linia1();
System.out.println(ncolcsol+" "+nlincsol);
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("becuri.out")));
out.close();
}
static void fac0Linia1()
{
10.4. BECURI
235
int i,j;
int nlc=0, ncc=0; // nr linii/coloane comutate
boolean ok=true;
for(j=1;j<=n;j++) colc[j]=0; // coloane necomutate inca
for(i=1;i<=m;i++) linc[i]=0; // linii necomutate inca
for(i=1;i<=m;i++) for(j=1;j<=n;j++) b[i][j]=a[i][j]; // copie
for(j=1;j<=n;j++)
if(b[1][j]==1)
{
comutaColoana(j);
colc[j]=1; // coloana j este comutata;
ncc++;
}
afisb();
for(i=2;i<=m;i++)
if(!okLinia(i)) {ok=false; break;}
else if(b[i][1]==1) { linc[i]=1; nlc++; }
if(ok&&(nlc+ncc<nlincsol+ncolcsol))
{
nlincsol=nlc;
ncolcsol=ncc;
for(i=1;i<=m;i++) lincsol[i]=linc[i];
for(j=1;j<=n;j++) colcsol[j]=colc[j];
}
}
static boolean okLinia(int i)
{
int j;
for(j=2;j<=n;j++) if(b[i][j]!=b[i][1]) return false;
return true;
}
static void comutaColoana(int j)
{
int i;
for(i=1;i<=m;i++) b[i][j]=(byte)((1+b[i][j])%2); // 0<-->1
}
static void comutaLinia(int i)
{
int j;
236
}
static void afisb()
{
int i,j;
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++) System.out.print(b[i][j]+" ");
System.out.println();
}
}
}
A doua faz
a: pun 1 pe prima linie si verific. Constatam ca se poate folosi
aceeasi metot
a dar cu un parametru pentru a transmite valoarea 0 sau 1.
import java.io.*;
class Becuri2
{
static int m,n;
static byte[][] a;
static byte[][] b;
static byte[] colc;
static byte[] linc;
static byte[] colcsol;
static byte[] lincsol;
static int ncolcsol=234, nlincsol=234;
public static void main(String[]args) throws IOException
{
int i,j,k;
BufferedReader br=new BufferedReader(new FileReader("becuri.in"));
StreamTokenizer st=new StreamTokenizer(br);
st.nextToken();m=(int)st.nval;
st.nextToken();n=(int)st.nval;
a=new byte[m+1][n+1];
b=new byte[m+1][n+1];
colc=new byte[n+1];
colcsol=new byte[n+1];
linc=new byte[m+1];
lincsol=new byte[m+1];
10.4. BECURI
237
for(i=1;i<=m;i++)
for(j=1;j<=n;j++) { st.nextToken(); a[i][j]=(byte)st.nval; }
facLinia1((byte)0);
facLinia1((byte)1);
System.out.println(ncolcsol+" "+nlincsol);
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("becuri.out")));
out.close();
}
static void facLinia1(byte val)
{
int i,j;
int nlc=0, ncc=0; // nr linii/coloane comutate
boolean ok=true;
for(j=1;j<=n;j++) colc[j]=0; // coloane necomutate inca
for(i=1;i<=m;i++) linc[i]=0; // linii necomutate inca
for(i=1;i<=m;i++) for(j=1;j<=n;j++) b[i][j]=a[i][j]; // copie
for(j=1;j<=n;j++)
if(b[1][j]!=val)
{
comutaColoana(j);
colc[j]=1; // coloana j este comutata;
ncc++;
}
afisb();
for(i=1;i<=m;i++) if(!okLinia(i)) { ok=false; break; }
else if(b[i][1]==1) { linc[i]=1; nlc++; }
if(ok&&(nlc+ncc<nlincsol+ncolcsol))
{
nlincsol=nlc;
ncolcsol=ncc;
for(i=1;i<=m;i++) lincsol[i]=linc[i];
for(j=1;j<=n;j++) colcsol[j]=colc[j];
}
}
static boolean okLinia(int i)
{
238
}
static void comutaColoana(int j)
{
int i;
for(i=1;i<=m;i++) b[i][j]=(byte)((1+b[i][j])%2); // 0<-->1
}
static void comutaLinia(int i)
{
int j;
for(j=1;j<=n;j++) b[i][j]=(byte)((1+b[i][j])%2); // 0<-->1
}
static void afisb()
{
int i,j;
for(i=1;i<=m;i++)
{
for(j=1;j<=n;j++) System.out.print(b[i][j]+" ");
System.out.println();
}
System.out.println();
}
}
Analog pentru prima coloana. n plus, se finalizeaz
a scrierea rezultatelor n
fisier.
10.4.3
Codul surs
a*
import java.io.*;
class Becuri3
{
static int m,n;
static byte[][] a;
static byte[][] b;
static byte[] colc;
static byte[] linc;
10.4. BECURI
239
240
10.4. BECURI
nlc++;
}
for(j=1;j<=n;j++)
if(!okColoana(j)) { ok=false; break;}
else if(b[1][j]==1) { colc[j]=1; ncc++; }
if(ok&&(nlc+ncc<nlincsol+ncolcsol))
{
nlincsol=nlc;
ncolcsol=ncc;
for(i=1;i<=m;i++) lincsol[i]=linc[i];
for(j=1;j<=n;j++) colcsol[j]=colc[j];
}
}
static boolean okLinia(int i)
{
int j;
for(j=2;j<=n;j++) if(b[i][j]!=b[i][1]) return false;
return true;
}
static boolean okColoana(int j)
{
int i;
for(i=2;i<=m;i++) if(b[i][j]!=b[1][j]) return false;
return true;
}
static void comutaColoana(int j)
{
int i;
for(i=1;i<=m;i++) b[i][j]=(byte)((1+b[i][j])%2); // 0<-->1
}
static void comutaLinia(int i)
{
int j;
for(j=1;j<=n;j++) b[i][j]=(byte)((1+b[i][j])%2); // 0<-->1
}
}
241
242
10.5
Discuri
Florin Ghetu, Bucuresti
Se dau N numere reale considerate ca fiind razele a N discuri.
Consider
am ca asezam un disc n sistemul xOy dac
a l plas
am la o coordonata x pozitiva suficient de mare, tangent cu axa Ox si deasupra ei, apoi l
mpingem spre Oy pana cand devine tangent cu Oy sau cu primul disc nt
alnit,
asezat anterior.
Dup
a asezarea tuturor discurilor n ordinea data unele dintre ele pot fi considerate dispensabile, pentru ca prin eliminarea lor nu se modific
a l
atimea totala
a figurii rezultate, adica nici un disc nu se mai poate deplasa spre stanga.
Cerint
a:
Identificati toate discurile dispensabile dintr-o configuratie data.
Date de intrare:
Din fisierul de intrare DISCURI.IN veti citi de pe prima linie num
arul N
de discuri, iar de pe urmatoarele N linii, N numere reale reprezent
and razele
discurilor n ordinea de asezare, cate unul pe linie.
Date de iesire:
In fisierul DISCURI.OUT veti scrie pe prima linie num
arul K de discuri
dispensabile, iar pe urmatoarele K linii, K ntregi reprezent
and numerele de ordine
ale discurilor considerate dispensabile, cate unul pe linie.
Restrictii:
N 1000.
243
10.5. DISCURI
DISCURI.IN
7
4
0.1
0.5
3
0.5
4
1
DISCURI.OUT
3
2
3
5
10.5.1
Indicatii de rezolvare *
Solutie prezentat
a n GInfo 12/6
Pentru identificarea discurilor dispensabile va trebui s
a determin
am atingerile
dintre discurile care influenteaz
a l
atimea figurii. De exemplu, dac
a avem sase discuri, cu raze de 1000, 1, 2, 3, 1000, respectiv 500, atunci atingerile care influenteaz
a
l
atimea figurii sunt ntre primul si al cincilea disc, respectiv ntre al cincilea si al
saselea.
Pentru fiecare disc i vom determina, pe r
and, coordonatele orizonatale pe
care le-ar avea discul dac
a ar atinge unul dintre discurile anterioare.
In final, vom alege discul (sau axa Oy) pentru care coordonata orizontala
a centrului noului disc este maxima si putem afirma ca discul i ajuge n aceast
a
pozitie.
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.
In final vom verifica dac
a exist
a discuri introduse la sfarsit care sunt dispensabile. Pentru aceasta vom determina l
atimea figurii si ultimul disc care o
influenteaz
a. Toate discurile introduse dupa acest disc sunt dispensabile.
Pentru determinarea coordonatei orizontale xi a centrului unui disc i care
atinge un disc j avem nevoie de coordonata orizontala xj a centrului discului j,
precum si de razele ri si rj 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:
p
xj = xi + (ri + rj )2 (ri rj )2 .
Analiza complexit
atii
Pentru fiecare disc i care este introdus, se determin
a posibila coordonat
a xi
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 operatii este O(N 2 .
244
La fiecare pas, pot fi marcate ca dispensabile cel mult toate discurile inserate
anterior, asadar ordinul de complexitate al acestei operatii este tot O(N 2 ).
Determinarea l
atimii figurii si a cercurilor dispensabile de la sfarsitul secventei
necesita a singur
a parcurgere a sirului care pastreaza coordonatele centrelor discurilor, ceea ce implic
a ordinul de complexitate O(N ).
Afisarea cercurilor dispensabile precum si citirea razelor cercurilor sunt operatii
care se efectueaza n timp liniar (O(N )), necesitand o simpla parcurgere a unor
siruri.
In concluzie, ordinul de complexitate al algoritmului de rezolvare a acestei
probleme este O(N 2 ) + O(N 2 ) + O(N ) + O(N ) + O(N ) = O(N 2 ).
10.5.2
Rezolvare detaliat
a
10.5.3
Codul surs
a*
import java.io.*;
class Discuri
{
static int ultimulDisc;
static double latime;
static boolean[] dispensabil;
static double[] r;
static double[] x;
static int n,k;
public static void main(String args[]) throws IOException
{
citeste();
calcul();
scrie();
}
static void citeste() throws IOException
{
BufferedReader br=new BufferedReader(new FileReader("discuri.in"));
StreamTokenizer st=new StreamTokenizer(br);
st.nextToken(); n=(int)st.nval;
r=new double[n+1];
x=new double[n+1];
dispensabil=new boolean[n+1];
// implicit este false
10.5. DISCURI
245
246
10.6
Cod
COD.OUT
55
COD.IN
aab
COD.OUT
0
COD.IN
vwxyz
COD.OUT
83681
10.6. COD
247
10.6.1
Indicatii de rezolvare *
Solutie prezentat
a n GInfo 12/6
Din conditiile precizate n enunt rezulta ca, pe baza unei multimi de litere
distincte, se poate construi un singur cuvant care respecta conditiile date, si anume
cel care contine literele ordonate lexicografic. Asadar, oric
arei multimi de cel mult
zece litere distincte i corespunde un cuvant care respecta conditiile din enunt.
Se poate afirma ca un cuvant este o submultime a multimii literelor; de aici
k
rezulta ca num
arul cuvintelor formate din k litere este C26
. Mai mult, num
arul
cuvintelor formate din k dintre ultimele n litere ale alfabetului este Cnk .
Numarul de ordine al cuvantului dat este mai mare decat cel al cuvintelor
formate din mai multe cifre. Din aceste motive,
un cunv
ant format din k
Pk pentru
i
litere, vom avea un num
ar mai mare decat i=1 C26
.
In continuare, pentru prima litera a cuvantului, va trebui s
a g
asim num
arul
cuvintelor care ncep cu o litera mai mica (din punct de vedere lexicografic).
In cazul n care cuvantul are k litere, vor exista C k1 cuvinte valide care k
25
k1
ncep cu a, C25
cuvinte valide care ncep cu b etc.
In general, vor exista C k1 cuvinte valide care ncep cu a i-a litera a alfa26i
betului.
Daca prima litera a cuvantului este cea de-a n-a litera a alfabetului, vom
P
n
k1
avea i=1 C26i
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
diferenta este data de faptul ca a doua litera trebuie s
a fie strict mai mare dec
at
prima. Asadar, dac
a prima literaPeste cea de-a n-a a alfabetului, iar a doua este
m1
k2
cea de-a m-a, atunci vom avea i=n+1 C26i
cuvinte care au pe prima pozitia
aceeasi litera, iar pe cea de-a doua pozitie o litera mai mica.
Procedeul va continua pentru fiecare 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 pozitii aceleasi litere
ca
s
i
cuv
a
ntul
dat,
iar
pe cea de-a p-a o
Pm1
kp
litera mai mica este dat de formula i=n+1 C26i
.
Adunand toate valorile obtinute pe parcurs vom obtine num
arul cuvintelor
care se afla naintea cuvantului dat. Adunand 1 la aceast
a valoare, vom obtine
num
arul de ordine al cuvantului.
Analiza complexit
atii
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
248
10.6.2
Rezolvare detaliat
a
10.6.3
Codul surs
a*
import java.io.*;
class Cod
{
static String cuvant;
static long codcuvant;
public static void main(String args[]) throws IOException
{
cuvant=citeste();
codcuvant=calcul();
scrie();
}
static String citeste() throws IOException
{
BufferedReader br=new BufferedReader(new FileReader("cod.in"));
String s=br.readLine();
br.close();
10.6. COD
249
return(s);
}
static long calcul()
{
int k=cuvant.length();
int i,j,m,n=0;
long nr=1;
for(i=1; i<k; i++) nr+=comb(26,i);
for(i=0; i<k; i++)
{
if(i>0)
{
n=cuvant.charAt(i-1)-a+1;
if(cuvant.charAt(i)<=cuvant.charAt(i-1)) return 0;
}
m=cuvant.charAt(i)-a+1;
for(j=n+1; j<m; j++) nr+=comb(26-j,k-i-1);
}
return nr;
}
static void scrie() throws IOException
{
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("cod.out")));
out.print(codcuvant);
out.close();
}
static long comb(int n,int k)
{
int i,j,d;
if(k>n/2) k=n-k;
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;
250
}
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;
}
}
Capitolul 11
Seti
Cercetatorii ce lucreaz
a la programul SETI au receptionat dou
a transmisii
de date foarte ciudate, date care ar putea veni din partea unor civilizatii extraterestre. Primul set de date este format din 10 caractere distincte, date n ordinea
lor lexicografic
a, ce formeaz
a alfabetul extraterestru. A doua transmisie contine
cuvinte din exact 4 caractere.
Cerint
a
Cercetatorii trebuie s
a ordoneze lexicografic cuvintele primite n a doua transmisie (conform alfabetului extraterestru).
Date de intrare
Fisierul de intrare seti.in contine pe prima linie cele 10 caractere ale alfabetului, iar pe fiecare din urmatoarele linii cate un cuvant.
Date de iesire
Fisierul de iesire seti.out va contine cuvintele ordonate, cate unul pe linie.
Restrictii si preciz
ari
In fisier nu sunt mai mult de 200.000 de cuvinte, iar caracterele sunt literele
mici ale alfabetului englez.
Datele de intrare se presupun ca fiind corecte.
Exemplu
251
252
seti.out
aaaa
aabc
fgaa
iihf
11.1.1
Indicatii de rezolvare *
Solutie prezentat
a de Mihai Stroe, GInfo nr. 13/6
Rezolvarea problemei const
a n realizarea unei metode de trecere de la cuvintele 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 fi memorate, n schimb se va folosi un tablou cu 10.000
de elemente, fiecare element reprezent
and num
arul de aparitii al unui cuvant din
fisier.
In final, pentru fiecare num
ar de la 0 la 9999, se va afisa cuvantul reprezentat
de at
atea ori de cate indic
a num
arul s
au de aparitii.
Pentru a trece de la cuvant la num
ar si invers se poate folosi ca etapa intermediara un tablou de patru cifre, transformarile realiz
andu-se foarte usor.
Analiza complexit
atii
Fie N num
arul de cuvinte din fisier care poate avea valoarea maxima 200.000.
Operatia de citirea a datelor are ordinul de complexitate O(N ).
Metodele care transforma cuvintele n numere si invers au ordinul de complexitate O(1).
Actualizarea tabloului care contorizeaz
a num
arul de aparitii se face concomitent cu citirea, deci aceast
a operatie are ordinul de complexitate O(N ).
Operatia de afisarea a datelor are ordinul de complexitate O(N ).
In final, ordinul de complexitate al algoritmului de rezolvare este O(N ) +
O(N ) + O(N ) = O(N ).
11.1.2
Rezolvare detaliat
a
11.1.3
Codul surs
a*
11.1. SETI
253
{
static
static
static
static
254
for(i=0;i<10000;i++)
if(f[i]>0)
{
cuvant=cuvantul(i);
for(nr=1;nr<=f[i];nr++) out.println(cuvant);
}
out.close();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}//main
static String cuvantul(int nr)
{
int r,i;
char[] c=new char[4];
for(i=0;i<4;i++) c[i]=caractercd[0];
i=3;
while(nr!=0)
{
r=nr%10;
c[i]=caractercd[r];
nr=nr/10;
i--;
}
String s=new String(c);
return s;
}
}//class
Versiune finala!
import java.io.*;
class Seti2
{
static int[] codd=new int[10];
static int[] codi=new int[26];
static char[] caractercd=new char[10];
static int[] f=new int[10000];
public static void main(String[]args) throws IOException
{
String alfabet,cuvant;
int i,nr;
11.1. SETI
255
long t1,t2;
t1=System.currentTimeMillis();
PrintWriter out = new PrintWriter(
new BufferedWriter(new FileWriter("seti.out")));
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("seti.in")));
st.nextToken(); alfabet=st.sval.toString();
for(i=0;i<10;i++)
{
codd[i]=alfabet.charAt(i)-a;
caractercd[i]=alfabet.charAt(i);
}
for(i=a;i<=z;i++) codi[i-a]=-1;
for(i=0;i<10;i++) codi[codd[i]]=i;
while(st.nextToken()!=st.TT_EOF) // preluarea cuvantului
{
cuvant=st.sval.toString(); // conversia in String
nr=0;
for(i=0;i<4;i++) nr=nr*10+codi[cuvant.charAt(i)-a];
f[nr]++;
}
for(i=0;i<10000;i++)
if(f[i]>0)
{
cuvant=cuvantul(i);
for(nr=1;nr<=f[i];nr++) out.println(cuvant);
}
out.close();
t2=System.currentTimeMillis();
System.out.println("Timp = "+(t2-t1));
}//main
static String cuvantul(int nr)
{
int i;
char[] c=new char[4];
for(i=0;i<4;i++) c[i]=caractercd[0];
i=3;
256
}
}//class
11.2
Scaune
19
18
17
16
15
14
13
12
11
10
Pe fiecare din aceste scaune este asezat un copil. Primul copil sta pe scaunul
1, iar ultimul pe scaunul ns. Pe l
anga cele ns scaune deja ocupate, alti nc copii
(1 nc ns) asteapt
a s
a se elibereze un loc.
La un moment dat un singur copil se ridic
a de pe scaun si pleac
a. Atunci, cat
timp n dreptul scaunului liber nu exist
a un copil, toti copiii aflati n asteptare se
misc
a n sens invers misc
arii acelor ceasornicului, cate o pozitie, pana cand unul
din ei ocupa locul liber.
Conditii:
la nceput toate scaunele sunt ocupate;
fiecare copil aflat n asteptare se afla initial n dreptul unui scaun ocupat;
cand un copil avanseaza cu n pozitii spre un loc pe scaun, toti cei care
asteapt
a avanseaza tot cu n pozitii. Deoarece miscarea este circular
a, avansarea
cu 4 pozitii de la pozitia 18, semnific
a o deplasare n dreptul pozitiei 2;
Cerint
a
Daca se da o secvent
a a numerelor de ordine a copiilor care pleac
a la fiecare
moment, s
a se scrie un program care s
a afiseze num
arul scaunului pe care s-a
asezat fiecare copil care asteapt
a, dac
a acest lucru este posibil.
Date de intrare
Pe prima linie a fisierului text de intrare scaune.in se afla dou
a numere,
separate prin spatiu, reprezent
and num
arul de scaune, ns si respectiv num
arul
257
11.2. SCAUNE
scaune.out
6 16
19 3
17 0
13 20
11
11.2.1
Indicatii de rezolvare *
Solutie prezentat
a de Mihai Stroe, GInfo nr. 13/6
Rezolvarea acestei probleme const
a n simularea deplasarii copiilor, conform
regulilor din enunt.
Deoarece limita pentru num
arul de scaune este destul de mica, avansarea
copiilor se poate realiza pas cu pas; astfel, n momentul n care un scaun se
elibereaza, fiecare copil avanseaza cate o pozitie pana cand unul dintre ei ajunge
n dreptul scaunului si l ocupa.
O metoda mai rapid
a const
a n calcularea, pentru fiecare copil, a num
arului
de mutari pana la ajungerea la scaunul liber.
Fie un copil situat n pozitia C, iar scaunul liber n pozitia S; atunci copilul
va avansa S C pozitii, dac
a C = S, respectiv N S + S C pozitii, dac
a C > S.
258
Astfel, la fiecare ridicare a unui copil se poate afla cel mai apropiat copil,
se calculeaz
a cate pozitii se va deplasa acesta (sa spunem P ), apoi toti copiii vor
avansa P pozitii. Un copil care avanseaza P pozitii din pozitia C va ajunge n
pozitia C + P (daca C + P = N S), respectiv C + P N S (daca C + P > N S).
Analiza complexit
atii
Deoarece sunt N C copii n asteptare, vor fi analizate cel mult N C ridic
ari de
pe scaun, indiferent dac
a mai urmeaz
a ceva n fisierul de intrare.
Daca sunt mai putin de N C copii care se ridic
a, atunci o parte dintre cei care
asteapt
a vor r
am
ane n picioare.
La fiecare moment n care se ridic
a un copil, avansarea pas cu pas a copiilor
aflati n asteptare pana la aszarea pe scaun a unuia dintre ei nu poate necesita mai
mult de N S pasi; fiecare pas necesita avansarea tuturor copiilor, deci a cel mult
N C copii.
Complexitatea ocuparii unui scaun prin avansare pas cu pas este deci O(N S
N C).
In cazul metodei mai rapide, calcularea distantei pentru toti copiii pana la
scaunul liber are complexitatea O(N C). Aceeasi complexitate au si operatiile de
alegere a minimului P dintre aceste distante, respectiv de avansare a tuturor copiilor cu P pozitii.
Ordinul de complexitate al algoritmului de rezolvare a acestei probleme este
O(N C N S N C) pentru prima variant
a, respectiv O(N C N C) pentru cea de-a
doua.
11.2.2
Rezolvare detaliat
a
11.2.3
Codul surs
a*
11.2. SCAUNE
259
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++)
if(!asezat[i])
{
pozFinala[i]++;
if(pozFinala[i]==ns+1) pozFinala[i]=1;
}
}
260
11.3. CIRCULAR
261
{
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
11.3
Circular
Unele numere naturale sunt formate doar din cifre distincte nenule.
Dintre acestea, unele, numite numere circulare, au urmatoarea proprietate:
262
circular.out
347 1849625
Semnificatie
Exist
a 347 numere circulare mai mici dac
at
1894250 cel mai mare dintre acestea fiind
num
arul 1849625
11.3.1
Indicatii de rezolvare *
Solutie prezentat
a de Mihai Stroe, GInfo nr. 13/6
O rezolvare foarte buna a acestei probleme se bazeaza pe faptul ca exista
foarte putine numere circulare ntre 10 si 10.000.000. Acestea pot fi generate n
timpul concursului, obtinandu-se un fisier cu toate numerele circulare, cate 10 pe
linie si separate prin virgul
a. Acest fisier poate fi transformat usor ntr-un vector
de constante care poate fi folosit de un program Pascal sau C/C++ care, astfel
11.3. CIRCULAR
263
contine toate numerele circulare. Acest program va citi valoarea lui N , apoi va
rezolva cerintele parcurgand vectorul de constante. Deci, concurentul va elabora
dou
a programe: cel de generare a numerelor circulare si cel care, folosindu-le,
rezolv
a cerintele 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 fiecare 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 mpartiri succesive la 10 cu salvarea restului.
Se observa ca se vor obtine 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 verifica foarte usor
dac
a este format din cifre distincte si nu contine cifra 0; pentru conditia r
amasa se
va num
ara spre dreapta, iar pozitiile pe care se opreste num
ararea vor fi marcate
cu 0. Daca la un moment dat se va ajunge pe o pozitie marcat
a cu 0, far
a a se fi
marcat n prealabil toate pozitiile, 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 C1 pe prima pozitie, se va trece la pozitia 1 + C1 (de fapt se vor
face C1 avans
ari spre dreapta) si se va continua de acolo; dac
a acolo se va folosi
cifra C2 , se avanseaza nca C2 pozitii spre dreapta etc.
La fiecare 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 pozitie deja
completata si mai sunt pozitii libere, num
arul n constructie nu poate fi circular
si se revine la cifra precedent
a.
Analiza complexit
atii
Pentru aceast
a problema, complexitatea rezolv
arii este data de num
arul M
de numere circulare, deci solutia ruleaza instantaneu, deci ordinul de complexitate
al acesteia ar fi O(log2 M ), n cazul n care se foloseste o cautare binara.
Deoarece M este o constant
a, ordinul de complexitate al solutiei este O(1).
Complexitatea metodei de generare a numerelor circulare depinde de metoda
folosita.
11.3.2
Rezolvare detaliat
a
11.3.3
Codul surs
a*
264
11.3. CIRCULAR
265
}
}//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
{
ok=true;
if(k>0)
for(j=0;j<k;j++) if(i==x[j]) {ok=false; break;}
266
}
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;
}
}
11.4
Criptare
Mircea si Vasilic
a vor s
a-si trimit
a mesaje pe care altii sa nu le nteleaga. Au
citit ei despre spioni si modalit
ati de a scrie mesaje si, n final, au imaginat un mod
de criptare a unui mesaj care foloseste cuvant cheie (le-a placut lor denumirea
asta :-) ).
267
11.4. CRIPTARE
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 fie incomplet
a, asa ca o completeaza cu spatii.
Apoi numeroteaz
a literele cuvantului cheie n ordinea aparitiei lor n alfabetul
englez.
In final, rescriu mesajul astfel: coloana de sub litera numerotat
a cu 1, urmat
a
de coloana de sub litera numerotat
a cu 2, etc. nlocuind totodata si spatiile cu
caracterul * (asterisc).
Exemplu:
cuvantul cheie:
mesaj de criptat:
cuvantul cheie
numerotare:
criptam
Incercam sa lucram cu coduri si criptari.
m
4
no
p
5
r
6
t
7
uvwxzy
codificare:
2
I
m
c
*
*
p
6
n
*
r
c
s
t
3
c
s
a
o
i
a
5
e
a
m
d
*
r
mesaj criptat:
clcrr.
col1
Imc**p
col2
7
r
*
*
u
c
i
1
c
l
c
r
r
.
4
a
u
u
i
i
*
clcrr.Imc**pcsaoiaauuii*eamd*rn*rcstr**uci
csaoia
col3
auuii*
col4
eamd*r
col5
n*rcst
col6
r**uci
col7
Cerint
a
Fiind date un cuvant cheie si un mesaj criptat, decodificati mesajul trimis de
Mircea pentru Vasilic
a.
Date de intrare
Fisierul de intrare criptare.in contine pe prima linie mesajul criptat iar pe
linia a doua cuvantul cheie.
Date de iesire
268
11.4.1
Indicatii de rezolvare *
Solutie prezentat
a de Mihai Stroe, GInfo nr. 13/6
Pentru decriptarea mesajului se utilizeaza algoritmul de criptare descris, n
sens invers.
Se determin
a ordinea literelor din cuvantul cheie. Consider
and ca acest cuvant
are lungimea L, iar textul are lungimea N , el va fi mpartit n L grupe de lungimea
N/L.
Grupele sunt asezate ntr-o matrice cu L coloane pe coloanele corespunzatoare
ordinii literelor din cuvantul cheie.
In final, matricea este parcurs
a pe linii si se afiseaza mesajul decriptat.
Analiza complexit
atii
Operatiile de citire si afisare a datelor au ordinul de complexitate O(N ).
Deoarece lungimea L a cuvantului cheie este mica, operatiile cu acesta (determinarea ordinii literelor) pot fi neglijate la calculul complexit
atii.
Scrierea cuvantului n matrice are ordinul de complexitate O(N ).
In final, ordinul de complexitate al algoritmului de rezolvare a acestei probleme este O(N ) + O(N ) = O(N ).
11.4.2
Rezolvare detaliat
a
import java.io.*;
class Criptare1
{
public static void main(String[]args)throws IOException
{
11.4. CRIPTARE
269
int i,j,k;
BufferedReader br=new BufferedReader(
new FileReader("criptare.in"));
String mesaj=br.readLine();
String cheia=br.readLine();
br.close();
System.out.println("mesajul este: "+mesaj+" "+mesaj.length());
System.out.println("cheia este: "+cheia+" "+cheia.length());
int m=mesaj.length()/cheia.length(); // nr linii matrice
int n=cheia.length(); // nr coloane matrice
int[] p=new int[n];
// sortare prin numarare
for(j=1; j<=n-1; j++)
for(i=0;i<=j-1;i++)
if(cheia.charAt(i)<cheia.charAt(j)) ++p[j]; else ++p[i];
afisv(p);
int[] pp=new int[n]; // permutarea inversa
for(i=0;i<n;i++) pp[p[i]]=i;
afisv(pp);
char a[][]=new char[m][n];
k=0;
for(j=0;j<n;j++)
for(i=0;i<m;i++)
{
a[i][pp[j]]=mesaj.charAt(k);
k++;
}
System.out.println("Matricea a[][] este:");
for(i=0;i<m;i++)
{
for(j=0;j<n;j++) System.out.print(a[i][j]+" ");
System.out.println();
}
for(i=0;i<m;i++)
for(j=0;j<n;j++)
if(a[i][j]!=*) System.out.print(a[i][j]);
else System.out.print(" ");
270
System.out.println();
}//main
static void afisv(int[] x)
{
int n=x.length, i;
for(i=0;i<n;i++) System.out.print(x[i]+" ");
System.out.println();
}
}//class:
11.4.3
Codul surs
a*
import java.io.*;
class Criptare2
{
public static void main(String[]args)throws IOException
{
int i,j,k;
BufferedReader br=new BufferedReader(
new FileReader("criptare.in"));
PrintWriter out=new PrintWriter(
new BufferedWriter(
new FileWriter("criptare.out")));
String mesaj=br.readLine();
String cheia=br.readLine();
br.close();
int m=mesaj.length()/cheia.length(); // nr linii matrice
int n=cheia.length(); // nr coloane matrice
int[] p=new int[n];
// sortare prin numarare
for(j=1; j<=n-1; j++)
for(i=0;i<=j-1;i++)
if(cheia.charAt(i)<cheia.charAt(j)) ++p[j]; else ++p[i];
int[] pp=new int[n]; // permutarea inversa
for(i=0;i<n;i++) pp[p[i]]=i;
char a[][]=new char[m][n];
k=0;
11.5. MAS
INA
271
for(j=0;j<n;j++)
for(i=0;i<m;i++)
{
a[i][pp[j]]=mesaj.charAt(k);
k++;
}
for(i=0;i<m;i++)
for(j=0;j<n;j++)
if(a[i][j]!=*) out.print(a[i][j]); else out.print(" ");
out.close();
}
}
11.5
cerc.
Masina
O tar
a are 3 N 30000 orase, numerotate de la 1 la N , dispuse pe un
272
masina.out
4
11.5.1
Indicatii de rezolvare *
Solutie prezentat
a de Mihai Stroe, GInfo nr. 13/6
Avand n vedere ca orasele sunt asezate si parcurse circular, putem dubla
orasele, iar apoi putem s
a le consideram asezate liniar:
an+1 = a1 , an+2 = a2 , ..., an+k = ak , ..., a2n = an
bn+1 = b1 , bn+2 = b2 , ..., bn+k = bk , ..., b2n = bn .
Cantitatea de benzina castigat
a n urma opririi n orasul i si parcurgerii
drumului catre orasul i + 1 este ci = ai bi . Evident, aceast
a cantitate poate fi
negativ
a.
Definim
Pi sirul sumelor partiale ale vectorului c astfel:
si = k=1 si .
Pentru ca PAM s
a poat
a efectua turul, este necesar ca suma cantitatii de
benzina acumulate s
a fie mai mare sau egal
a cu 0, deci sn = 0.
Rezolvarea problemei const
a n a g
asi un x astfel ncat
cx 0, cx + cx1 0, ..., cx + cx+n1 0,
adica
sx sx1 0, sx+1 sx1 0,..., sx+n1 sx1 0.
Un candidat viabil este pozitia m n pentru care sm este minim.
11.5. MAS
INA
273
In continuare se demonstreaz
a ca aceast
a alegere conduce la o solutie.
Fie m < k n; avem sk sm (din definitia lui m).
Fie n < k; avem
sk = c1 + ... + cn + cn+1 + ... + ck = sn + c1 + ... + ck = sn + sk sk sm
(am folosit faptul ca sn 0).
In concluzie x = m + 1 este o solutie pentru problema.
Implementarea const
a n citirea datelor, calcularea sirului sumelor partiale si
g
asirea minimului dintre s1 , s2 , ..., sn .
Analiza complexit
atii
Operatia de citire a datelor are ordinul de complexitate O(n).
Calculul sirului sumelor partiale are ordinul de complexitate O(n) pentru ca
si = si1 + ai .
Minimul din acest sir se calculeaz
a cu aceeasi complexitate.
Operatia de scriere a rezultatului are ordinul de complexitate O(1).
In final, ordinul de complexitate al algoritmului de rezolvare a acestei probleme este O(n) + O(n) + O(1) = O(n).
11.5.2
Rezolvare detaliat
a
11.5.3
Codul surs
a*
import java.io.*;
class Masina
{
public static void main(String[] args) throws IOException
{
int i,rez;
int j,n;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("masina.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("masina.out")));
st.nextToken();n=(int)st.nval;
int[] a=new int[n+1];
int[] b=new int[n+1];
for (j=1;j<=n;j++){ st.nextToken();a[j]=(int)st.nval;}
for (j=1;j<=n;j++){ st.nextToken();b[j]=(int)st.nval;}
274
for(i=1;i<=n;i++)
{
rez=a[i]-b[i];
j=i;
j++; if(j==n+1) j=1;
while((rez>=0)&&(j!=i))
{
rez=rez+a[j]-b[j];
j++;if(j==n+1) j=1;
}
if(rez>=0) {out.println(i); break;}
}
out.close();
}
}
11.6
Operatii
275
11.6. OPERAT
II
j num
arul operatiilor efectuate asupra celui de al doilea num
ar n, pe
linia i+2
op1 k1 pe urmatoarele j linii: perechi de numere
...
reprezent
and operatia (1 sau 2) si respectiv valoarea lui k
opj kj pentru operatia respectiv
a, separate printr-un spatiu
Restrictii
1 < m, n 2.000.000.000
Exemplu
OPERATII.IN
11 45
OPERATII.OUT
15
2
23
12
2
22
24
11.6.1
Indicatii de rezolvare *
Solutie prezentat
a de Mihai Stroe, GInfo nr. 13/6
Pentru rezolvarea problemei este necesara descompunerea n binar a celor
dou
a numere si ntelegerea efectului pe care l au cele dou
a operatii asupra acestei
descompuneri.
Se observa ca operatia O1 insereaza o cifra 1 n descompunere, pe o anumita
pozitie, n timp ce operatia O2 sterge un 0, la alegere.
Privind astfel cele dou
a operatii, algoritmul de rezolvare ncepe cu descompunerea numerelor n baza 2 si stergerea tuturor cifrelor 0 din ambele numere. Se
vor obtine astfel dou
a numere, nu neap
arat egale, ale caror descompuneri n baza
2 sunt formate numai din cifre 1 (deci numerele sunt de forma 2 P 1).
Cum cifrele 1 nu pot fi sterse, singura variant
a de a ajunge la acelasi num
ar
const
a n inserarea de cifre 1 n cadrul num
arului mai mic.
La efectuarea operatiilor O2 pe fiecare num
ar, acestea se memoreaz
a pentru
a fi afisate.
Pentru operatiile O1 nu este necesara memorarea; ele se vor efectua numai
asupra num
arului care r
am
ane mai mic, valoarea pentru K put
and fi 1 pentru
toate aceste operatii.
Analiza complexit
atii
Operatia de citire a datelor are ordinul de complexitate O(1).
De asemenea, ordinul de complexitate al operatiilor de descompunere a numerelor n baza 2, de detectare a zerourilor din descompunere, de memorare a
276
11.6.2
Rezolvare detaliat
a
11.6.3
Codul surs
a*
import java.io.*;
class Operatii
{
static int m, n;
static int[] a=new int[64]; // vectorul cifrelor binare ale lui m
static int[] b=new int[64]; // vectorul cifrelor binare ale lui n
static int nca,ncb, nc1a, nc0a, nc1b,nc0b, nc1sol,nminsol;
public static void main(String[]args) throws IOException
{
int i,j,k,nr;
PrintWriter out = new PrintWriter(
new BufferedWriter(new FileWriter("operatii.out")));
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("operatii.in")));
st.nextToken(); m=(int)st.nval;
st.nextToken(); n=(int)st.nval;
nr=m;
k=0;
while(nr!=0) { a[k]=nr%2; k++; nr=nr/2;}
nca=k;
nc1a=0;
for(k=0;k<nca;k++) if(a[k]==1) nc1a++;
nc0a=nca-nc1a;
nr=n;
k=0;
nc1b=0;
while(nr!=0) { b[k]=nr%2; k++; nr=nr/2;}
ncb=k;
11.6. OPERAT
II
for(k=0;k<ncb;k++) if(b[k]==1) nc1b++;
nc0b=ncb-nc1b;
if(nc1a<nc1b) nc1sol=nc1b; else nc1sol=nc1a;
nminsol=1;
for(k=1;k<=nc1sol;k++) nminsol=nminsol*2;
nminsol=nminsol-1;
out.println(nminsol);
out.println(nc1sol-nc1a+nc0a);
j=0;
for(k=1;k<=nc0a;k++)
{
while(a[j]!=0) j++;
out.println(2+" "+(j-k+2)); // sterg 0 de pe pozitia j
j++;
}
for(k=nc1a;k<nc1sol;k++) out.println("1 1");
out.println(nc1sol-nc1b+nc0b);
j=0;
for(k=1;k<=nc0b;k++)
{
while(b[j]!=0) j++;
out.println(2+" "+(j-k+2)); // sterg 0 de pe pozitia j
j++;
}
for(k=nc1b;k<nc1sol;k++) out.println("1 1");
out.close();
}//main
}//class
277
278
Capitolul 12
Coduri
coduri.out
625
1250
280
12.1.1
Indicatii de rezolvare *
12.1.2
Rezolvare detaliat
a*
si ne sugereaza s
a consideram codurile sub forma xk = k.
Pentru suma cuburilor obtinem
x31 + x32 + ... + x3n = 3
n(n + 1)
2
2
n(n + 1)(2n + 1)
n(n + 1)(2n + 1)
= 3
6
6
n(n + 1)(2n + 1)
=
6
2
n(n + 1)(2n + 1)
6
4
12.2. LOGIC
12.1.3
281
Codul surs
a*
import java.io.*;
class Coduri
{
public static void main(String[] args) throws IOException
{
int n;
int k;
long s;
long[] x;
PrintWriter out = new PrintWriter(
new BufferedWriter(new FileWriter("coduri.out")));
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("coduri.in")));
st.nextToken(); n=(int)st.nval;
x=new long[n+1];
s=n*(n+1)*(2*n+1)/6;
s=s*s*s*s;
for(k=1;k<=n;k++) x[k]=k*s;
for(k=1;k<=n;k++) out.println(x[k]);
out.close();
}
}
12.2
Logic
Demonstrarea automat
a a teoremelor si verificarea satisfiabilitatii unei formule constituie dou
a capitole importante n cadrul logicii matematice.
Formulele propozitionale sunt alc
atuite din variabile propozitionale (variabile
care pot lua doar dou
a valori: sau adevarat sau fals) si din operatorii logici si, sau,
negatie, echivalent, implic
a.
Iat
a cateva exemple de formule propozitionale:
~p&(q <=> p) => q
p|q <=> ~p&~q
p
p => q => a => t => ~p
In acest exemplu, p si q sunt variabilele propozitionale, ~ este operatorul unar
negatie, & este operatorul binar si, | este operatorul binar sau, => este implicatia
logic
a (si apare numai n acest sens, nu si <=), iar <=> este echivalenta logic
a.
282
(A)
~A
A&B
A|B
A => B
A <=> B
dac
a valoarea sa de adevar
dac
a este adevarata A
A este adevarata
dac
a at
at A cat si B
A este fals si B este fals
dac
a ~A|B este adevarata
dac
a (A => B)&(B => A)
283
12.2. LOGIC
logic.out
4
1
12.2.1
Indicatii de rezolvare *
Informatia n formul
a nu apar mai mult de 10 litere mici ale alfabetului
latin ne conduce la ideea de a genera toate configuratiile (sunt cel mult 210 =
1024) si a calcula valoarea de adevar a formulei pentru fiecare configuratie. Se
foloseste recursivitatea tinand cont de priorit
atile operatorilor.
12.2.2
Rezolvare detaliat
a*
284
System.out.println("&
System.out.println("|
System.out.println("<
System.out.println("=
System.out.println(">
System.out.println("a
System.out.println("z
out.close();
}//main
}//class
"+(int)&);
"+(int)|);
"+(int)<);
"+(int)=);
"+(int)>);
"+(int)a);
"+(int)z);
12.2. LOGIC
285
286
}
static boolean si()
{
System.out.println(" --> si "+poz+" "+e[poz]);
boolean a, b, val;
a=not();
val=a;
if((poz<n)&&(e[poz]==&)) {poz++; b=si(); val=(a&&b);}
if(poz<n) System.out.println("<-- si "+poz+" "+e[poz]);
else System.out.println("<-- si "+poz);
return val;
}
static boolean not()
{
boolean val;
System.out.println(" --> not "+poz+" "+e[poz]);
if(e[poz]==~) {poz++; val=!not();}
else val=paranteza();
if(poz<n) System.out.println("<-- not "+poz+" "+e[poz]);
else System.out.println("<-- not "+poz);
return val;
}
static boolean paranteza()
{
System.out.println(" --> paranteza "+poz+" "+e[poz]);
boolean val;
if(e[poz]==() {poz++;val=formula(); poz++;}
else if(e[poz] == )) val=false;
else val=variabila();
if(poz<n) System.out.println("<-- paranteza "+poz+" "+e[poz]);
else System.out.println("<-- paranteza "+poz);
return val;
}
static boolean variabila()
{
System.out.println(" --> variabila "+poz+" "+e[poz]);
boolean val;
if((poz<n)&&(e[poz]>=a)&&(e[poz]<=z)) val=v[(int)e[poz++]];
else val=formula();
12.2. LOGIC
287
12.2.3
Codul surs
a*
288
}
static boolean echivalenta()
{
boolean a,b,val;
a=implicatie();
val=a;
if((poz<n)&&(e[poz]==<)) {poz+=3; b=formula(); val=(a==b);}
return val;
}
static boolean implicatie()
{
boolean a, b, val;
a=sau();
val=a;
if((poz<n)&&(e[poz]===)) {poz+=2; b=implicatie(); val=(!a)||b;}
return val;
}
static boolean sau()
{
boolean a, b, val;
a=si();
val=a;
if((poz<n)&&(e[poz]==|)) {poz++; b=sau(); val=(a||b);}
return val;
}
static boolean si()
{
boolean a, b, val;
a=not();
val=a;
if((poz<n)&&(e[poz]==&)) {poz++; b=si(); val=(a&&b);}
return val;
}
static boolean not()
{
boolean val;
12.3. POLIGON
289
12.3
Poligon
290
POLIGON.OUT
6
12.3.1
Indicatii de rezolvare *
291
12.3. POLIGON
12.3.2
Rezolvare detaliat
a
12.3.3
Codul surs
a*
import java.io.*;
class Poligon
{
static int m,n,k,nsol=0;
static int[] x, y, d;
static int[] a=new int[5];
static int[][] ePunctIn=new int[101][101];
// =i ==> e punctul i
// =0 ==> nu e punct acolo
public static void main(String[] args) throws IOException
{
int i,j,ymax;
long t1,t2;
t1=System.nanoTime();
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("poligon.out")));
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("poligon.in")));
st.nextToken(); m=(int)st.nval;
st.nextToken(); n=(int)st.nval;
st.nextToken(); k=(int)st.nval;
x=new int[k+1];
y=new int[k+1];
d=new int[k+1];
for(i=1;i<=k;i++)
{
st.nextToken(); y[i]=(int)st.nval;
st.nextToken(); x[i]=(int)st.nval;
st.nextToken(); d[i]=(int)st.nval;
}
// linia
// coloana
// directia
ymax=y[1];
for(i=2;i<=k;i++) if(y[i]>ymax) ymax=y[i];
for(i=1;i<=k;i++) y[i]=ymax-y[i]+1;
// sa fie "normal"!
for(i=1;i<=k;i++) ePunctIn[y[i]][x[i]]=i;
292
generezCombinariPePozitia(1);
out.println(nsol);
out.close();
t2=System.nanoTime();
System.out.println("Timp = "+((double)(t2-t1))/1000000000);
}
static void generezCombinariPePozitia(int j)
{
int i;
for(i=a[j-1]+1;i<=k-4+j;i++)
{
a[j]=i;
if(j<4) generezCombinariPePozitia(j+1);
else if(ePoligonOK()) nsol++;
}
}
static boolean ePoligonOK()
{
if(coliniare3Puncte()) return false;
if(ePoligon(a[1],a[2],a[3],a[4])) return
if(ePoligon(a[1],a[2],a[4],a[3])) return
if(ePoligon(a[1],a[3],a[2],a[4])) return
if(ePoligon(a[1],a[3],a[4],a[2])) return
if(ePoligon(a[1],a[4],a[2],a[3])) return
if(ePoligon(a[1],a[4],a[3],a[2])) return
return false;
}
static boolean coliniare3Puncte()
{
if(coliniare(a[1],a[2],a[3])) return
if(coliniare(a[1],a[2],a[4])) return
if(coliniare(a[1],a[3],a[4])) return
if(coliniare(a[2],a[3],a[4])) return
return false;
}
true;
true;
true;
true;
true;
true;
true;
true;
true;
true;
12.3. POLIGON
293
s=x[p1]*y[p2]+x[p2]*y[p3]+x[p3]*y[p1];
s=s-y[p1]*x[p2]-y[p2]*x[p3]-y[p3]*x[p1];
if(s==0) return true; else return false;
}
static boolean ePoligon(int p1, int p2, int p3, int p4)
{
if(!eLinie(p1,p2)) return false;
if(!eLinie(p2,p3)) return false;
if(!eLinie(p3,p4)) return false;
if(!eLinie(p4,p1)) return false;
if(eNedegenerat(p1,p2,p3,p4)) return true; else return false;
}
static boolean eLinie(int p1, int p2) // trece prin coordonate intregi!
{
if(Math.abs(x[p1]-x[p2])==Math.abs(y[p1]-y[p2])) return eLinieOkOblica(p1,p2);
else if(x[p1]==x[p2]) return eLinieOkVerticala(p1,p2);
else if(y[p1]==y[p2]) return eLinieOkOrizontala(p1,p2);
else return false;
}
static boolean eLinieOkOrizontala(int p1, int p2)
{
int i;
if(x[p1]>x[p2]) {i=p1;p1=p2;p2=i;} // p1 ... p2
for(i=x[p1]+1; i<=x[p2]; i++)
{
if(ePunctIn[y[p1]][i]==0) return false;
else if((d[ePunctIn[y[p1]][i]]&(1<<1))==0) // linie spre V
return false;
}
return true;
}
static boolean eLinieOkVerticala(int p1, int p2)
{
int i;
if(y[p1]>y[p2]) {i=p1;p1=p2;p2=i;} // p1 ... p2
for(i=y[p1]+1; i<=y[p2]; i++)
if(ePunctIn[i][x[p1]]==0) return false;
else if((d[ePunctIn[i][x[p1]]]&(1<<3))==0) // linie spre S
294
}
static boolean eLinieOkOblica(int p1, int p2)
{
int i,j,pasy,dir;
if(x[p1]>x[p2]) {i=p1;p1=p2;p2=i;} // p1 ... p2
if(y[p1]>y[p2]) {pasy=-1; dir=0;} // NV
else {pasy=+1; dir=2;} // SV
i=y[p1];
for(j=x[p1]+1; j<=x[p2]; j++)
{
i=i+pasy;
if(ePunctIn[i][j]==0) return false;
else if((d[ePunctIn[i][j]]&(1<<dir))==0) // linie spre SV sau NV
return false;
}
return true;
}
static boolean eNedegenerat(int p1, int p2, int p3, int p4)
{
// daca nu se intersecteaza p1p4 cu p2p3
if(!seIntersecteaza(x[p1],y[p1],x[p4],y[p4],x[p2],y[p2],x[p3],y[p3]))
return true; else return false;
}
static boolean seIntersecteaza( int x1,int y1,int x2,int y2,
int x3,int y3,int x4,int y4)
{
// daca se intersecteaza segmentele [p1p2] cu [p3p4]
// p3 si p4 sunt in semiplane diferite fata de dreapta (p1p2) si
// p1 si p2 sunt in semiplane diferite fata de dreapta (p3p4)
return (s(x3,y3,x1,y1,x2,y2)*s(x4,y4,x1,y1,x2,y2)<0) &&
(s(x1,y1,x3,y3,x4,y4)*s(x2,y2,x3,y3,x4,y4)<0);
}
static int s(int xp,int yp,int xa,int ya,int xb,int yb)
{
//de ce parte a dreptei ((xa,ya);(xb,yb)]) se afla (xp,yp)
double s=(double)yp*(xb-xa)-xp*(yb-ya)+xa*yb-xb*ya;
12.4. SABLON
295
12.4
S
ablon
Gigel si Vasilic
a imagineaza un mod de a transmite mesaje pe care nimeni s
a
nu le poat
a descifra. Mesajul este ascuns ntr-un text care are N linii si pe fiecare
linie sunt exact N caractere - litere mari ale alfabetului englez, cifre, semne de
punctuatie si caracterul spatiu.
Decodificarea se face cu ajutorul unui sablon, de aceleasi dimensiuni ca si
textul, care are cateva g
auri.
Suprapun
and sablonul peste text r
aman vizibile cateva caractere.
Acestea se citesc n ordinea liniilor, de sus n jos, iar pe aceeasi linie de la
stanga la dreapta.
Apoi hartia cu textul se roteste spre stanga, n sens trigonometric, cu 90o ,
sablonul r
am
anand fix. Alte caractere devin vizibile si acestea se citesc n acelasi
mod.
Operatia se repeta de nca dou
a ori (rotire cu 180o , respectiv cu 270o ), pana
cand textul ajunge, printr-o nou
a rotatie cu 90o , din nou n pozitia initiala.
Din pacate, sablonul pentru codificare/decodificare s-a pierdut. In schimb a
r
amas la Gigel mesajul initial iar la Vasilic
a a ajuns textul care contine mesajul.
Cerint
a
Sa se reconstituie sablonul care a fost folosit la codificare.
Date de intrare
Fisierul de intrare sablon.in contine
pe prima linie, mesajul initial
pe linia a doua a fisierului de intrare se g
aseste valoarea N
urmatoarele N linii contin textul care ascunde mesajul.
Date de iesire
Fisierul de iesire sablon.out contine N linii a cate N caractere. Caracterele
sunt O (pentru reprezentarea unei g
auri) si X.
Restrictii si
prin rotirea textului nici una din g
auri nu se va suprapune peste nici una
din pozitiile ocupate de o gaur
a n pozitiile precedente ale textului
1 N 50
mesajul are maxim 1000 caractere si se ncheie cu un caracter diferit de
spatiu
296
sablon.out
XXXXOXXXXX
XXOXXXXXXX
OXXXXXXXXX
XXXOXXXXXX
XOXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
12.4.1
Indicatii de rezolvare *
Solutia oficial
a
Problema se rezolv
a relativ simplu tinand cont de urmatoarele observatii:
1. Deoarece ntregul mesaj a fost codificat prin 4 rotiri ale textului, este clar
ca la o pozitionare a textului sub sablon pot fi citite Lung(M esaj)/4 caractere,
deci ntregul mesaj are 4 N umarGauri caractere
2. Ca urmare a observatiei de la punctul 1, mesajul poate fi mpartit exact
n 4 siruri de lungimi egale M esaj1, ..., M esaj4
3. Daca o gaur
a se afla n pozitia T [i, j] din sablon, ei i corespund pozitiile
T [j, N i + 1] la rotire cu 90 grade
T [N i + 1, N j + 1] la rotire cu 180 grade
T [N j + 1, i] la rotire cu 270 grade
de unde deducem ca nu e nevoie s
a rotim textul!!!
4. Daca lungimea unui sir este L4 (vezi n sursa), este suficient s
a parcurgem
numai primul din cele 4 siruri cu un Index. Atunci, parcurgand textul care ascunde
mesajul, n pozitia (i, j) exist
a o gaur
a n sablon dac
a si numai dac
a toate cele 4
caractere
M esaj1[Index], M esaj2[Index], M esaj3[Index], M esaj4[Index]
coincid cu cele 4 caractere obtinute prin rotire (vezi observatia 3)
5. Cel mai bun pseudocod este... PASCAL-ul, deci: ... (urmeaza sursa n
Pascal).
12.4. SABLON
12.4.2
297
Rezolvare detaliat
a*
12.4.3
Codul surs
a*
import java.io.*;
class Sablon1
{
static int n;
static String mesajInitial; // mesajul initial
static char[][] text; // text (codificarea)
static boolean[][] gaura;
298
299
12.5. SIR
{ // daca toate 4 caractere coincid
gaura[i][j]=true;
k++;
if(k>=nrGauri) return;
}
}
12.5
S
ir
Gigel se distreaz
a construind siruri crescatoare de numere din multimea
{1, 2, ..., n}. La un moment dat observa ca unele siruri, de cel putin k termeni
(k 3), au o proprietate mai aparte: diferenta dintre doi termeni consecutivi este
constant
a. Iat
a cateva exemple de astfel de siruri pentru n 21:
2,3,4
1,5,9,13
7,10,13,16,19,21
Cerint
a
Dandu-se num
arul natural n ajutati-l pe Gigel s
a numere cate astfel de siruri
poate s
a construiasca.
Date de intrare
In fisierul de intrare sir.in se g
aseste, pe prima linie, num
arul n.
Date de iesire
In fisierul de iesire sir.out se va afisa, pe prima linie, num
arul cerut urmat
de caracterul sf
arsit de linie.
Restrictii:
3 n 20000
300
12.5.1
Indicatii de rezolvare *
Solutia oficial
a
Notand cu r diferenta dintre doi tereni consecutivi constat
am ca pentru r = 1
se pot construi urmatoarele submultimi, siruri cu proprietea ceruta, de lungime 3:
{1, 2, 3}, {2, 3, 4}, ..., {n 2, n 1, n}.
Cele de lungime superioar
a se construiesc adaugand elemente pe cele deja
Pn2
obtinute. Numarul lor va fi i=1 i.
Similar pentru r = 2 obtinem urmatoarele submultimi, siruri de lungime 3:
{1, 3, 5}, {2, 4, 6}, ..., {n4, n2, n} sau {n5, n3, n1} functie de paritatea lui n .
Cele de lungime superioara se construiesc adaugand elemente pe acestea.
Numarul lor este o sum
a te tipul precedent.
Se continua astfel pana la r = n/2, valoarea maxima a lui r.
12.5.2
Rezolvare detaliat
a
12.5.3
Codul surs
a*
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(
12.6. SNIPERS
301
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();
}
}
12.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 fie observati.
Cand s
a fie data comanda de tragere s-a constatat ca nu se transmisese
fiecarui trag
ator ce capetenie s
a mpuste, iar dac
a doi trag
atori ar fi tras n aceeasi
capetenie sau traiectoriile razelor ucigase s-ar fi intersectat, atunci ar fi sc
apat cel
putin o capetenie care ar fi putut duce r
azboiul pana la cap
at, iar trolii ar fi 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 putin de o secunda s
a transmit
a fiecarui trag
ator n ce capetenie s
a traga.
Voi puteti face asta?
Cerint
a
Scrieti un program care, citind pozitiile trag
atorilor si a capeteniilor, determina capetenia n care trebuie s
a traga fiecare trag
ator.
Date de intrare
Fisierul de intrare snipers.in contine
pe prima sa linie num
arul n
pe urmatoarele n linii se afla perechi de numere ntregi, separate prin spatiu,
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 contine n linii.
302
snipers.out
1
2
snipers.in
5
66
4 12
28
94
52
6 11
97
39
14
73
snipers.out
2
5
1
3
4
12.6.1
Indicatii de rezolvare *
Solutia oficial
a
La nceput fiec
arui tragator i i asociem capetenia i, dupa care vom lua n
considerare toate perechile trag
ator-c
apetenie si vom elimina ncrucisarile razelor,
la cate dou
a perechi prin interschimbarea tintelor trag
atorilor.
303
12.6. SNIPERS
12.6.2
Rezolvare detaliat
a
12.6.3
Codul surs
a*
import java.io.*;
class Snipers
{
static int n;
static int[] xt, yt, xc, yc, t, c;
static PrintWriter out;
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
citire();
rezolvare();
afisare();
}
static void citire() throws IOException
{
int k;
st=new StreamTokenizer(new BufferedReader(new FileReader("snipers.in")));
st.nextToken(); n=(int)st.nval;
xt=new int[n+1];
yt=new int[n+1];
xc=new int[n+1];
yc=new int[n+1];
t=new int[n+1]; // tragator --> capetenie
for(k=1;k<=n;k++)
{
st.nextToken();
st.nextToken();
}
for(k=1;k<=n;k++)
{
st.nextToken();
st.nextToken();
xt[k]=(int)st.nval;
yt[k]=(int)st.nval;
xc[k]=(int)st.nval;
yc[k]=(int)st.nval;
304
}
static void rezolvare() throws IOException
{
int i,j,aux;
boolean seIntersecteaza_ij,ok;
for(i=1;i<=n;i++) t[i]=i; // tragatorul i trage in capetenia i
if(n==1) return;
do
{
ok=true; // am gasit o combinatie valida tragator-capetenie
i=1;
do
{
j=i;
do
{
j=j+1;
seIntersecteaza_ij=seIntersecteaza(xt[i],yt[i],xc[t[i]],yc[t[i]],
xt[j],yt[j],xc[t[j]],yc[t[j]]);
if(seIntersecteaza_ij)
{
aux=t[i];t[i]=t[j];t[j]=aux; // interschimbam tintele
ok=false;
// nu avem combinatie buna
}
} while ((j!=n) && !seIntersecteaza_ij);
if(!seIntersecteaza_ij) i++; // trecem la urmatorul sniper
} while(i!=n); // pana terminam lista de tragatori
} while(!ok);
}
//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;
else if(s>0.001) return 1;
else return 0;
}
// testeaza daca segmentul[a1,b1] se intersecteaza cu [a2,b2]
static boolean seIntersecteaza(int xa1,int ya1,int xb1,int yb1,
int xa2,int ya2,int xb2,int yb2)
12.6. SNIPERS
305
{
// a2 si b2 se afla de o parte si de alta a lui [a1,b1] si
// a1 si b1 se afla de o parte si de alta a lui [a2,b2]
return (s(xa2,ya2,xa1,ya1,xb1,yb1)*s(xb2,yb2,xa1,ya1,xb1,yb1)<0) &&
(s(xa1,ya1,xa2,ya2,xb2,yb2)*s(xb1,yb1,xa2,ya2,xb2,yb2)<0);
}
static void afisare() throws IOException
{
int k;
out=new PrintWriter(new BufferedWriter(new FileWriter("snipers.out")));
for(k=1;k<=n;k++) out.println(t[k]);
out.close();
}
}
306
Capitolul 13
Bifo
Autor: Silviu G
anceanu
Pentru a-si vindeca rana provocata de Sp
anul cel Negru, printul Algorel
are nevoie de leacul miraculos aflat n posesia vrajitoarei din padurea ntunecat
a.
Aceasta i-a promis leacul dac
a i rezolv
a urmatoarea problema, la care ea
s-a g
andit zadarnic o mie de ani: pornind de la dou
a cuvinte initiale A1 si A2 si
aplicand formula bifo An = An2 An1 pentru n 3, se obtin cuvintele A3 , A4 ,
A5 , s.a.m.d.
Prin An2 An1 ntelegem concatenarea cuvintelor An2 si An1 n aceast
a
ordine.
Toate aceste cuvinte (A1 , A2 , A3 , s.a.m.d), sunt la r
andul lor concatenate, n
ordine, formand un sir de caractere infinit denumit sir magic.
Formula leacului miraculos are M caractere, pe care vrajitoarea nu le stie.
Se stiu ns
a cele M pozitii din sirul magic n care apar, n ordine, caracterele din
formula.
Cerint
a
Cu toata inteligenta lui, Algorel nu poate rezolva aceast
a problema. Ajutati-l
pe print s
a iasa din ncurc
atur
a afland formula leacului magic.
Date de intrare
Primele dou
a linii ale fisierului bifo.in contin fiecare cate un sir de cel mult
100 de caractere reprezent
and cuvintele A1 (pe prima linie) si respectiv A2 (pe a
doua linie).
A treia linie contine un num
ar ntreg M , reprezent
and num
arul de caractere
din formula leacului miraculos.
Urmeaza M linii descriind, n ordine, pozitiile din sirul magic unde se g
asesc
caracterele din formula.
307
308
Date de iesire
Fisierul de iesire bifo.out va contine pe prima linie un sir de M caractere
reprezent
and formula leacului miraculos.
Restrictii si preciz
ari
1 M 100;
A1 si A2 contin doar litere mici ale alfabetului englez;
Numerotarea pozitiilor din sirul infinit ncepe cu 1;
Cele M pozitii vor fi numere ntregi (nu neaparat distincte) de maxim 100
de cifre;
Pentru 60% din teste pozitiile vor fi numere ntregi ntre 1 si 1.000.000.000;
Fiecare linie din fisierul de intrare si din fisierul de iesire se termin
a cu
marcaj de sf
arsit de linie;
Exemplu
bifo.in bifo.out
ab
xdb
cdx
3
10
4
15
Explicatie: Primele 5 siruri obtinute folosind formula bifo sunt:
ab, cdx, abcdx, cdxabcdx, abcdxcdxabcdx
Concatenand aceste siruri se obtine sirul magic:
abcdxabcdxcdxabcdxabcdxcdxabcdx...
Timp maxim de executie/test: 1 sec sub Windows si 1 sec sub Linux
13.1.1
Indicatii de rezolvare *
Solutia oficial
a, Silviu G
anceanu
Utilizand formula bifo se obtine un sir de cuvinte A1, A2, A3, s.a.m.d, care
este practic un sir Fibonacci de cuvinte. Fie Li lungimea cuvantului Ai din acest
sir. Pentru a afla ce caracter se afla pe pozitia X din sirul magic se procedeaz
a n
modul urmator :
pas1 : se g
aseste cel mai mic K astfel ncat L1 + L2 + ... + LK X (termenul
din sirul de cuvinte unde se g
aseste pozitia X)
pas2 : se scade din valoarea X suma L1 + L2 + ... + LK1 pentru a afla pozitia
din termenul K unde este caracterul din pozitia X
pas3 :
1. dac
a K < 3 se afiseaz
a caracterul de pe pozitia X din cuvantul corespunzator
2. altfel, stiind lungimile cuvintelor AK2 si AK1 si stiind ca AK se obtine
13.1. BIFO
309
13.1.2
Rezolvare detaliat
a
310
13.1. BIFO
311
13.1.3
Codul surs
a*
Variant
a far
a numere mari.
import java.io.*;
class Bifo2
{
static int m;
static char[] a1;
static char[] a2;
static char[] f;// formula
static int[] p; // pozitii
static int[] lg;// lungimile cuvintelor a[i]=a[i-2]a[i-1]
static PrintWriter out;
static BufferedReader br;
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
int i;
citire();
for(i=1;i<=m;i++) rezolvare(i);
afisare();
}
static void citire() throws IOException
{
int i,j;
br=new BufferedReader(new FileReader("bifo.in"));
st=new StreamTokenizer(br);
st.nextToken(); a1=st.sval.toCharArray();
st.nextToken(); a2=st.sval.toCharArray();
st.nextToken(); m=(int)st.nval;
f=new char[m+1];
p=new int[m+1];
312
}
static void rezolvare(int i)
{
int x,k,sk1,sk,pk;
lg[1]=a1.length;
lg[2]=a2.length;
x=p[i];
if(x<=lg[1]){ f[i]=a1[x-1]; return; }
if(x<=lg[1]+lg[2]){ f[i]=a2[x-lg[1]-1]; return; }
sk1=lg[1];
sk=sk1+lg[2];
k=2; // k=cuvantul unde se gaseste caracterul de pe pozitia x
while(sk<x)
{
k++;
lg[k]=lg[k-2]+lg[k-1];
sk1=sk;
sk=sk1+lg[k];
}
x=x-sk1;
while(k>2)
// a[k]=a[k-2]a[k-1]
{
if(lg[k-2]>=x) // caracterul este in a[k-2] stanga
{
k=k-2;
}
else
// caracterul este in a[k-1] dreapta
{
x=x-lg[k-2];
k--;
}
}
if(k==1) f[i]=a1[x-1];
if(k==2) f[i]=a2[x-1];
13.1. BIFO
313
}
static void afisare() throws IOException
{
int i;
out=new PrintWriter(new BufferedWriter(new FileWriter("bifo.out")));
for(i=1;i<=m;i++) out.print(f[i]);
out.println();
out.close();
}
}
Variant
a cu numere mari.
import java.io.*; // Fibo[481]=101 cifre
class Bifo3
{
static int m;
static char[] a1;
static char[] a2;
static char[] f; // formula
static char[][] p; // pozitii
static char[][] lg=new char[482][1];// lungimile cuvintelor a[i]=a[i-2]a[i-1]
static PrintWriter out;
static BufferedReader br;
static StreamTokenizer st;
public static void main(String[] args) throws IOException
{
int i;
citire();
for(i=1;i<=m;i++) rezolvare(i);
afisare();
}
static void citire() throws IOException
{
int i,j;
char aux;
br=new BufferedReader(new FileReader("bifo.in"));
st=new StreamTokenizer(br);
st.nextToken(); a1=st.sval.toCharArray();
st.nextToken(); a2=st.sval.toCharArray();
st.nextToken(); m=(int)st.nval;
314
}
static void rezolvare(int i)
{
char[] x,sk1,sk,pk;
int k;
lg[1]=nr2v(a1.length);
lg[2]=nr2v(a2.length);
x=suma(nr2v(0),p[i]); // improvizatie pentru x=p[i];
!!!
if(compar(x,lg[1])<=0){f[i]=a1[v2nr(x)-1];return;}
if(compar(x,suma(lg[1],lg[2]))<=0){f[i]=a2[v2nr(x)-v2nr(lg[1])-1];return;}
sk1=suma(nr2v(0),lg[1]);
sk=suma(sk1,lg[2]);
k=2; // k=cuvantul unde se gaseste caracterul de pe pozitia x
while(compar(sk,x)<0)
{
k++;
lg[k]=suma(lg[k-2],lg[k-1]);
sk1=suma(nr2v(0),sk);
sk=suma(sk1,lg[k]);
}
x=scade(x,sk1);
while(k>2) // a[k]=a[k-2]a[k-1]
{
if(compar(lg[k-2],x)>=0) // caracterul este in a[k-2] stanga
{
13.1. BIFO
315
k=k-2;
}
else // caracterul este in a[k-1] dreapta
{
x=scade(x,lg[k-2]);
k--;
}
}
if(k==1) f[i]=a1[v2nr(x)-1];
if(k==2) f[i]=a2[v2nr(x)-1];
}
static void afisare() throws IOException
{
int i;
out=new PrintWriter(new BufferedWriter(new FileWriter("bifo.out")));
for(i=1;i<=m;i++) out.print(f[i]);
out.println();
out.close();
}
static int compar(char[] a, char[] b) //-1, 0, 1 ... a < = > b
{
int na=a.length;
int nb=b.length;
if(na>nb) return 1; else if(na<nb) return -1;
int i=na-1;
while((i>=0)&&(a[i]==b[i])) i--;
if(i==-1) return 0;
else if(a[i]>b[i]) return 1; else return -1;
}
static char[] scade(char[] x,char[] y) // z=x-y unde x>=y
{
int nx=x.length;
int ny=y.length;
int nz=nx;
int i,s;
char t;
char[] z=new char[nz];
char[] yy=new char[nz];
for(i=0;i<ny;i++) yy[i]=y[i];
t=0;
316
}
static char[] suma(char[] x,char[] y)
{
int nx=x.length;
int ny=y.length;
int nz;
if(nx>ny) nz=nx+1; else nz=ny+1;
int t,i;
char[] z=new char[nz];
char[] xx=new char[nz];
char[] yy=new char[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]=(char)(xx[i]+yy[i]+t);
t=z[i]/10;
z[i]=(char)(z[i]%10);
}
if(z[nz-1]!=0) return z;
else
{
char[] zz=new char[nz-1];
for(i=0;i<nz-1;i++) zz[i]=z[i];
return zz;
}
}
13.2. ROMEO
317
13.2
Romeo
318
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 portiune de un segment vertical (consum: 1J).
Total consum energie: 1 + 3 + 3 + 1 = 8J.
Cerint
a
Scrieti un program care citeste x si y si care afiseaza num
arul minim de J
consumati pentru tot drumul de la pozitia (0, 0) la pozitia (x, y), merg
and doar n
directiile precizate.
Date de intrare
Fisierul de intrare romeo.in contine numerele x si y pe prima linie, separate
de un spatiu.
Date de iesire
Fisierul de iesire romeo.out contine o singur
a linie cu num
arul de J consumati
pentru distanta totala parcurs
a din pozitia de plecare pana n cea finala.
Restrictii si preciz
ari
x si y sunt numere naturale;
0 x, y 40000
Fiecare linie din fisierul de intrare si din fisierul de iesire se ncheie cu
marcaj de sfarsit de linie.
Exemplu
romeo.in
32
romeo.out
5
2
1
0
Explicatie
13.2. ROMEO
319
13.2.1
Indicatii de rezolvare *
Solutia oficial
a, profesor Dan Grigoriu
Solutia descrisa este realizata didactic si se bazeaza pe un calcul algebric
simplu; solutia nu contine structuri repetive.
Energia pentru segmentele orizontale este n toate cazurile aceeasi: X.
Problema r
am
ane 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 directa spre
Nord, pana la strada orizontala a destinatiei, dupa care (daca este cazul), se merge
pe acea strada pana la destinatie, pe orizontala, ca n desenul alaturat.
320
Semnificatia ecuatiilor:
(1): (num
arul de portiuni verticale de lungime Z) + (num
arul de portiuni
verticale de lungime Z + 1) = (num
arul total de portiuni verticale, adica X + 1).
(2): (lungimea totala a portiunilor de lungime Z) + (lungimea totala a
potiunilor de lungime Z + 1) = (distanta totala de parcurs pe verticala, adica
Y ).
Odat
a obtinute M si N , energia pe verticala se va calcula ca fiind suma dintre
E1 = energia pentru cele M portiuni de lungime Z si E2 = energia pentru cele N
portiuni de lungime Z + 1.
E1 + E2 = M (1 + 2 + 3 + + Z) + N (1 + 2 + 3 + + (Z + 1)).
321
13.2. ROMEO
13.2.2
Rezolvare detaliat
a*
Rezolvarea
h
i sistemului conduce la n = y (x + 1)z si m = x + 1 y + (x + 1)z
y
unde z = x+1 iar energia totala este
m
13.2.3
(z + 1)(z + 2)
z(z + 1)
+n
+ x.
2
2
Codul surs
a*
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();
}
}
322
13.3
Seceta
lect. Ovidiu Domsa
Gr
adinile roditoare ale B
ar
aganului sufera anual pierderi imense din
cauza secetei. C
autatorii de apa au g
asit n fant
ani din care doresc s
a alimenteze n
gr
adini. Fie Gi , Fi , i = 1, ..., n puncte n plan reprezent
and puncte de alimentare
ale gr
adinilor si respectiv punctele n care se afla fant
anile. Pentru fiecare punct
se dau coordonatele ntregi (x, y) n plan.
Pentru a economisi materiale, leg
atura dintre o gr
adina si o fant
ana se realizeaza printr-o conduct
a n linie dreapta. Fiecare fant
ana alimenteaza o singur
a
gr
adina. Consiliul Judetean Galati plateste investitia cu conditia ca lungimea totala a conductelor s
a fie 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 fiecare gr
adina
cu exact o fant
ana.
Date de intrare
Fisierul de intrare seceta.in va contine:
Pe prima linie se afla num
arul natural n, reprezent
and num
arul gr
adinilor
si al fant
anilor.
Pe urmatoarele n linii se afla perechi de numere ntregi Gx Gy , separate
printr-un spatiu, reprezent
and coordonatele punctelor de alimentare ale gr
adinilor.
Pe urmatoarele n linii se afla perechi de numere ntregi Fx Fy , separate
printr-un spatiu, reprezent
and coordonatele punctelor fant
anilor.
Date de iesire
Fisierul de iesire seceta.out va contine:
m un num
ar natural reprezent
and partea ntreag
a a costului minim total
al conductelor.
Restrictii si preciz
ari
1 < n < 13
Nu exist
a trei puncte coliniare, indiferent dac
a sunt gr
adini sau fant
ani
Orice linie din fisierele de intrare si iesire se termina prin marcajul de sfarsit
de linie.
Exemplu
323
13.3. SECETA
seceta.in
3
14
33
47
23
25
31
seceta.out
624
Explicatie
Costul minim este [6.24264 * 100]=624
prin legarea perechilor:
Gradini
Fantani
14
23
33
31
47
25
Timp maxim de executie/test: 1 sec sub Windows si 0.5 sec sub Linux.
13.3.1
Indicatii de rezolvare *
Solutia oficial
a, lect. Ovidiu Domsa
Numarul mic al punctelor permite generarea tuturor posibilitatilor de a conecta
o gr
adina cu o fant
ana neconectata la un moment dat.
Pentru fiecare astfel de combinatie g
asit
a se calculeaz
a suma distantelor
(Gi, F j), n linie dreapta, folosind formula p
distantei 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 solutie implementata corect asigura 60 70 de puncte.
Pentru a obtine punctajul maxim se tine cont de urmatoarele aspecte:
1. Se construieste n prealabil matricea distantelor d(i, j) cu semnificatia
distantei 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 solutii optime se foloseste
proprietatea patrulaterului ca suma a doua laturi opuse (conditie care asigura
unicitatea conect
arii 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. Conditia de intersectie 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 afle de aceeasi parte a segmentului AB si respectiv
pentru segmentul CD, punctele A si B s
a se afle de aceeasi parte (se nlocuieste
n ecuatia dreptei ce trece prin dou
a puncte, studiat
a n clasa a 9-a).
Observatie: Pentru cei interesati, problema are solutie si la un nivel superior,
folosind algoritmul de determinare a unui flux maxim de cost minim.
13.3.2
Rezolvare detaliat
a
13.3.3
Codul surs
a*
Variant
a cu determinarea intesectiei segmentelor.
324
13.3. SECETA
325
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(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]];
326
}
// 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
}
// 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;
}
}
13.3. SECETA
327
328
}
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();
st.nextToken();
}
for(k=1;k<=n;k++)
{
st.nextToken();
st.nextToken();
}
xg[k]=(int)st.nval;
yg[k]=(int)st.nval;
xf[k]=(int)st.nval;
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;
13.3. SECETA
329
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))
{
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]);
}
330
331
13.3. SECETA
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();
st.nextToken();
}
for(k=1;k<=n;k++)
{
st.nextToken();
st.nextToken();
}
xg[k]=(int)st.nval;
yg[k]=(int)st.nval;
xf[k]=(int)st.nval;
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;}
332
}
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.*;
13.3. SECETA
333
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;
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++)
334
}
}// citire(...)
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
}// 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(...)
13.4. BIBLOS
335
13.4
Biblos
336
biblos.out
16
biblos.out
836
13.4.1
Indicatii de rezolvare *
Solutia oficial
a, Maria si Adrian Nita
13.4. BIBLOS
337
13.4.2
Rezolvare detaliat
a
13.4.3
Codul surs
a*
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")));
338
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;
339
13.4. BIBLOS
else max=smax[n-1];
Variant
a far
a vectori (optimizat spatiul 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")));
340
13.5
Joc
Cristina Luca
Pe o tabl
a patrat
a de dimensiune n n se deseneaza o secventa 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
figura). 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 figura.
3
a
a a
a a a
1 a a a a 2
Jocul const
a n alipirea cate unui nou triunghi la unul din v
arfurile 2 sau 3 ale
triunghiului curent. Daca se al
atur
a coltului 2, noul triunghi se aseaza cu v
arful 1
n prelungirea laturii [1, 2] a triunghiului curent, iar dac
a se al
atur
a coltului 3 se
13.5. JOC
341
aseaza cu v
arful 1 n prelungirea laturii [2, 3].
Initial 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.
In caz contrar, se face o singur
arotatie cu 90o spre stanga, obtinandu-se o nou
a
orientare a triunghiului. Daca nici n acest caz noul triunghi nu poate fi plasat,
jocul se opreste.
Zona ocupat
a de primul triunghi se completeza cu litera a; zona celui de-al
doilea se completezacu litera b, s.a.m.d. Cand literele mici ale alfabetului englez
sunt epuizate, se rencepe de la a.
Cerint
a
Cunosc
andu-se dimensiunea tablei, pozitia primului triunghi (linie, coloana)
si lungimea catetei precum si o secvent
a de triunghiuri care se doresc a fi alipite
se cere s
a se genereze matricea rezultat
a n finalul jocului.
Jocul se termin
a dac
a un triunghi nu mai poate fi alipit sau au fost plasate
toate triunghiurile descrise n secvent
a.
Date de intrare
In fisierul de intrare joc.in, pe prima linie se afla n (dimensiunea tablei).
Pe a doua linie separate prin cate un spatiu se afla: L (linia), C (coloana) si Lg
(lungimea catetei) corespunzatoare primului triunghi. Urm
atoarele linii, pan
a la
sfarsitul fisierului, contin cate dou
a numere naturale separate prin cate un singur
spatiu reprezent
and coltul triunghiului curent la care va fi alipit triunghiul urmator
si dimensiunea catetei triunghiului urmaor.
Date de iesire
In fisierul de iesire joc.out va fi afisata matricea rezultat
a. Celulele tablei
care nu sunt completate cu litere ale alfabetului vor fi completate cu ..
Restrictii si preciz
ari
1 n 100; 1 C, L n; 2 Lg n
Fiecare linie din fisierul de intrare si din fic serul de iec sre se termina cu
marcaj de sfarsit de linie.
Exemplu
342
joc.out
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
j j j i
j j . i
j . . i
k . . i
k k . .
k k k l
. . . l
. . . .
. . . .
. . . .
. . . .
.
.
.
.
.
.
.
.
.
i
i
i
.
.
.
l
.
.
.
.
.
.
.
.
.
.
.
.
.
i
i
.
.
.
.
m
m
m
.
.
.
.
.
.
.
.
.
h
h
i
.
.
.
.
.
.
m
m
.
.
.
.
.
.
.
.
.
h
.
.
.
.
.
.
.
a
.
m
.
.
.
.
.
.
.
.
.
g
g
g
.
.
.
.
a
a
.
n
n
n
.
.
.
.
.
.
.
g
g
.
.
.
.
a
a
a
.
.
n
n
.
.
f
f
f
f
f
g
.
.
.
b
a
a
a
a
.
.
.
n
.
.
f
f
f
f
.
.
.
.
b
b
.
.
.
.
.
.
.
.
.
.
f
f
f
.
.
.
.
b
b
b
.
.
.
.
.
.
.
.
.
.
f
f
.
.
.
.
b
b
b
b
.
.
.
.
.
.
.
.
.
.
f
.
.
d
.
b
b
b
b
b
.
.
.
.
.
.
.
.
.
.
e
.
.
d
d
.
.
.
.
c
.
.
.
.
.
.
.
.
.
.
e
e
.
d
d
d
.
.
c
c
.
.
.
.
.
.
.
.
.
.
e
e
e
d
d
d
d
c
c
c
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Explicatii
Triunghiul a este plasat n linia 16 coloana 8 si are latura 4.
Triunghiul b se alipeste n coltul 3 si are lungimea 5.
Triunghiul c se alipeste n coltul 2 si are lungimea 3.
Tringhiurile a, b si c pastreaza aceeasi aranjare.
Triunghiul d nu se poate alipi n aceeasi aranjare coltului 3 deoarece are
cateta de lungimea 4 si depaseste tabla. Rotim triunghiul cu 90o spre stanga si
obtinem o nou
a aranjare.
Triunghiul e se alipeste n coltul 2 si are cateta de lungime 3 n aranjarea
curent
a.
Triunghiul f nu se poate alipi n aceeasi aranjare cu e n coltul 3 deoarece
are cateta de lungimea 5 si depaseste tabla. Rotim triunghiul cu 90o spre stanga
si obtinem o nou
a aranjare. Triunghiul f se alipeste n coltul 3, are lungimea 5 si
o nou
a aranjare.
Algoritmul continua pana la al 14-lea triunghi, n.
Al 15-lea triunghi nu se mai poate plasa.
Timp maxim de executie/test: 0.2 sec n Windows si 0.2 sec sub Linux
13.5.1
Indicatii de rezolvare *
13.5. JOC
343
Solutia oficial
a, Cristina Luca
Solutia problemei const
a n gestionarea spatiului unei matrice folosind propriet
ati ale indicilor, parcurgerea pe linii, pe coloane, pe diagonale, fiecare n dou
a
sensuri.
Plasarea triunghiurilor pe tabla de joc presupune verificarea urmatoarelor
dou
a situatii:
1. cel putin un element al zonei triunghiului care urmeaz
a s
a fie plasat se afla
n afara tablei;
a. n exemplul de mai jos situatiile triunghiurilor d, f, k, triunghiuri care
nu pot fi plasate n aceeasi orientare cu cele care le preced deoarece lungimile
catetelor depasesc marginile dreapta, sus, respectiv staanga ale matricei;
b. dac
a triunghiul k ar fi plasat n pozitia 2 fata de triunghiul j ar avea
v
arful n afara tablei;
2. cel putin un element al zonei triunghiului care urmeaz
a s
a fie plasat se
suprapune peste un element al unui triunghi deja plasat.
Verificarea celor dou
a situati se face si dac
a se ncearc
a rotirea cu 90o a
triunghiului. De exemplu, dac
a triunghiul d nu este rotit apare situatia 1.a. De
aceea el este rotit obtinandu-se noua orientare n care nu apar situatiile 1 sau 2.
Exist
a dou
a situatii n care jocul se opreste:
se epuizeaz
a secventa de triunghiuri descrise n fisier;
triunghiul nu poate fi plasat nici direct nici dupa o singur
a rotire; restul
triunghiurilor nu vor mai fi luate n considerare: n exemplul de mai jos ultimul
triunghi, (24), nu va mai fi plasat.
Exemplu
344
joc.out
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
j j j i
j j . i
j . . i
k . . i
k k . .
k k k l
. . . l
. . . .
. . . .
. . . .
. . . .
.
.
.
.
.
.
.
.
.
i
i
i
.
.
.
l
.
.
.
.
.
.
.
.
.
.
.
.
.
i
i
.
.
.
.
m
m
m
.
.
.
.
.
.
.
.
.
h
h
i
.
.
.
.
.
.
m
m
.
.
.
.
.
.
.
.
.
h
.
.
.
.
.
.
.
a
.
m
.
.
13.5.2
Rezolvare detaliat
a
13.5.3
Codul surs
a*
.
.
.
.
.
.
.
g
g
g
.
.
.
.
a
a
.
n
n
n
.
.
.
.
.
.
.
g
g
.
.
.
.
a
a
a
.
.
n
n
.
.
f
f
f
f
f
g
.
.
.
b
a
a
a
a
.
.
.
n
.
.
f
f
f
f
.
.
.
.
b
b
.
.
.
.
.
.
.
.
.
.
f
f
f
.
.
.
.
b
b
b
.
.
.
.
.
.
.
.
.
.
f
f
.
.
.
.
b
b
b
b
.
.
.
.
.
.
.
.
.
.
f
.
.
d
.
b
b
b
b
b
.
.
.
.
.
.
.
.
.
.
e
.
.
d
d
.
.
.
.
c
.
.
.
.
.
.
.
.
.
.
e
e
.
d
d
d
.
.
c
c
.
.
.
.
.
.
.
.
.
.
e
e
e
d
d
d
d
c
c
c
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
import java.io.*;
class Joc
{
static int n;
static int[][] a;
static int val; // numar/caracter de umplere: 0,1,...,25 ==> (val+1)%26
static int dir; // directia: 0,1,2,3 circular ==> (dir+1)%4
public static void main(String[] args) throws IOException
{
long t1,t2;
t1=System.currentTimeMillis();
int v,d,i,j;
int l1, c1, d1;
13.5. JOC
345
boolean ok=true;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("joc.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("joc.out")));
st.nextToken(); n=(int)st.nval;
a=new int[n+1][n+1];
for(i=1;i<=n;i++) for(j=1;j<=n;j++) a[i][j]=-1;
st.nextToken(); l1=(int)st.nval; // linia varful 1
st.nextToken(); c1=(int)st.nval; // coloana varful 1
st.nextToken(); d1=(int)st.nval; // latura
val=0;
dir=0;
if(esteGol0(l1,c1,d1)) umple0(l1,c1,d1);
else if(esteGol1(l1,c1,d1)) {dir=(dir+1)%4; umple1(l1,c1,d1);}
while(ok&&(st.nextToken()!=StreamTokenizer.TT_EOF))
{
v=(int)st.nval;
st.nextToken(); d=(int)st.nval;
val=(val+1)%26;
if(v==2)
switch(dir)
{
case 0: if(esteGol0(l1,c1+d1,d)) // direct
{
c1=c1+d1; d1=d; umple0(l1,c1,d1);
}
else if(esteGol1(l1,c1+d1,d)) // rotit
{
c1=c1+d1; d1=d;
dir=(dir+1)%4;
umple1(l1,c1,d1);
}
else ok=false;
break;
case 1: if(esteGol1(l1-d1,c1,d)) // direct
{
l1=l1-d1; d1=d; umple1(l1,c1,d1);
}
346
347
13.5. JOC
l1=l1-d1; c1=c1+d1-1; d1=d;
dir=(dir+1)%4;
umple1(l1,c1,d1);
}
else ok=false;
break;
case 1: if(esteGol1(l1-d1+1,c1-d1,d)) // direct
{
l1=l1-d1+1; c1=c1-d1; d1=d; umple1(l1,c1,d1);
}
else if(esteGol2(l1-d1+1,c1-d1,d)) // rotit
{
l1=l1-d1+1; c1=c1-d1; d1=d;
dir=(dir+1)%4;
umple2(l1,c1,d1);
}
else ok=false;
break;
case 2: if(esteGol2(l1+d1,c1-d1+1,d)) // direct
{
c1=c1-d1+1; l1=l1+d1; d1=d; umple2(l1,c1,d1);
}
else if(esteGol3(l1+d1,c1-d1+1,d)) // rotit
{
c1=c1-d1+1; l1=l1+d1; d1=d;
dir=(dir+1)%4;
umple3(l1,c1,d1);
}
else ok=false;
break;
case 3: if(esteGol3(l1+d1-1,c1+d1,d)) // direct
{
l1=l1+d1-1;c1=c1+d1; d1=d; umple3(l1,c1,d1);
}
else if(esteGol0(l1+d1-1,c1+d1,d)) // rotit
{
l1=l1+d1-1;c1=c1+d1; d1=d;
dir=(dir+1)%4;
umple0(l1,c1,d1);
}
else ok=false;
break;
default: System.out.println("Ciudat!!!");
}
348
}
static void umple0(int lin, int col, int d) // 12=sd==>dir=0
{
int i,j,k;
for(k=0;k<d;k++)
{
i=lin-k;
for(j=col+k;j<col+d;j++) a[i][j]=val;
}
}
static boolean esteGol0(int lin, int col, int d)
{
int i,j,k;
if((lin-0>n)||(lin-d+1<1)||(col<1)||(col+d-1>n)) return false;
boolean gol=true;
for(k=0;k<d;k++)
{
i=lin-k;
for(j=col+k;j<col+d;j++) if(a[i][j]!=-1){ gol=false;break;}
}
return gol;
}
static void umple1(int lin, int col, int d) // 12=js==>dir=1
{
int i,j,k;
for(k=0;k<d;k++)
{
i=lin-k;
13.5. JOC
349
for(j=col-k;j<=col;j++) a[i][j]=val;
}
}
static boolean esteGol1(int lin, int col, int d)
{
int i,j,k;
if((lin-0>n)||(lin-d+1<1)||(col-d+1<1)||(col>n)) return false;
boolean gol=true;
for(k=0;k<d;k++)
{
i=lin-k;
for(j=col-k;j<=col;j++) if(a[i][j]!=-1) {gol=false; break;}
}
return gol;
}
static void umple2(int lin, int col, int d) // 12=ds==>dir=2
{
int i,j,k;
for(k=0;k<d;k++)
{
i=lin+k;
for(j=col-d+1;j<=col-k;j++) a[i][j]=val;
}
}
static boolean esteGol2(int lin, int col, int d)
{
int i,j,k;
if((lin<1)||(lin+d-1>n)||(col-d+1<1)||(col>n)) return false;
boolean gol=true;
for(k=0;k<d;k++)
{
i=lin+k;
for(j=col-d+1;j<=col-k;j++) if(a[i][j]!=-1){ gol=false;break;}
}
return gol;
}
static void umple3(int lin, int col, int d) // 12=sj==>dir=3
{
int i,j,k;
for(k=0;k<d;k++)
350
}
static boolean esteGol3(int lin, int col, int d)
{
int i,j,k;
if((lin<1)||(lin+d-1>n)||(col<1)||(col+d-1>n)) return false;
boolean gol=true;
for(k=0;k<d;k++)
{
i=lin+k;
for(j=col;j<=col+k;j++) if(a[i][j]!=-1) {gol=false; break;}
}
return gol;
}
}
13.6
Pal
Autor: Silviu G
anceanu
Printul Algorel este n ncurc
atur
a din nou: a fost prins de Sp
anul cel
Negru n ncercarea sa de a o salva pe printes
a si acum este nchis n Turnul cel
Mare.
Algorel poate evada dac
a g
aseste combinatia magic
a cu care poate deschide
poarta turnului.
Printul stie cum se formeaz
a aceast
a combinatie magic
a: trebuie s
a utilizeze
toate cifrele scrise pe usa turnului pentru a obtine dou
a numere palindroame,
astfel ncat suma lor s
a fie minima, iar aceast
a suma este combinatia magic
a ce va
deschide usa.
Primul num
ar palindrom trebuie s
a aiba cel putin L cifre, iar cel de-al doilea
poate avea orice lungime diferita de 0. Numerele palindroame formate nu pot
ncepe cu cifra 0. Acum interveniti dumneavoastr
a n poveste, fiind prietenul s
au
cel mai priceput n algoritmi.
Prin noul super-telefon al s
au, printul transmite num
arul de aparitii a fiecarei
cifre de pe usa turnului precum si lungimea minima L a primului num
ar, iar
dumneavoastr
a trebuie s
a-i trimiteti cat mai repede numerele cu care poate obtine
combinatia magic
a.
Cerint
a
Avand datele necesare, aflati dou
a numere palindroame cu care se poate
obtine combinatia magic
a.
351
13.6. PAL
Date de intrare
Prima linie a fisierului pal.in contine un num
ar ntreg L reprezent
and lungimea minima a primului num
ar. Urmeaza 10 linii: pe linia i + 2 se va afla un
num
ar ntreg reprezent
and num
arul de aparitii ale cifrei i, pentru i cu valori de la
0 la 9.
Date de iesire
Prima linie a fisierului de iesire pal.out contine primul num
ar palidrom, iar
cea de-a doua linie contine cel de-al doilea num
ar palindrom. Daca exista mai
multe solutii se va scrie doar una dintre ele.
Restrictii si preciz
ari
Explicatie
Pentru acest exemplu avem L = 5,
3 cifre de 0, 2 cifre de 1si 3 cifre de 2.
Cifrele de la 3 la 9 lipsesc
de pe usa turnului.
Cele dou
a palindroame cu care
se genereaza combinatia magic
a
sunt 10001 si 222.
Combinatia magic
a va fi suma acestora
si anume 10223 (care este suma minima
pe care o putem obtine).
13.6.1
Indicatii de rezolvare *
Solutia oficial
a, Silviu G
anceanu
352
Problema se rezolv
a utiliz
and tehnica greedy. Notam num
arul total de cifre
cu N C. Se observa ca, pentru ca suma celor dou
a numere palindroame s
a fie
minima, trebuie ca lungimea maxima a celor dou
a numere s
a fie cat mai mica.
Asadar, pentru nceput, se stabileste lungimea exact
a a primului num
ar (care va
fi cel mai lung), n functie de L n modul urmator:
1. dac
a L < N C/2, atunci lungimea primului palindrom va fi aleasa astfel
ncat cele dou
a numere s
a fie cat mai apropiate ca lungime
2. dac
a L >= N C/2 apar cazuri particulare si se stabileste dac
a lungimea
primului palindrom creste sau nu cu o unitate.
Avand lungimile numerelor stabilite putem merge mai departe utilz
and strategia greedy, observand ca cifrele mai mici trebuie s
a ocupe pozitii cat mai semnificative. Pentru a realiza acest lucru se vor completa n paralel cele dou
a numere
cu cifrele parcurse n ordine crescatoare stabilind n care din cele dou
a numere
se vor pozitiona. De asemenea, trebuie avut n vedere ca niciunul din cele dou
a
numere s
a nu nceap
a cu cifra 0.
Datele de test au fost construite astfel ncat si solutii neoptime s
a obtina
puncte, gradat, n functie de optimiz
arile efectuate asupra implement
arii.
13.6.2
Rezolvare detaliat
a
13.6.3
Codul surs
a*
13.6. PAL
353
st.nextToken();L=(int)st.nval;
for(i=0;i<=9;i++) { st.nextToken(); fc[i]=(int)st.nval;}
for(i=0;i<=9;i++) NC+=fc[i];
// nr total cifre
for(i=0;i<=9;i++) ncfi=ncfi+(fc[i]%2); // nr cifre cu frecventa impara
nc1=L;
nc2=NC-nc1;
while(nc1<nc2) {nc1++; nc2--;}
if((ncfi==2)&&(nc1%2==0)) {nc1++; nc2--;}
p1=new int[nc1];
p2=new int[nc2];
switch(ncfi)
{
case 0: impare0(); break;
case 1: impare1(); break;
case 2: impare2(); break;
default: System.out.println("Date de intrare eronate!");
}
corectez(p1);
corectez(p2);
for(i=0;i<p1.length;i++) out.print(p1[i]);
out.println();
for(i=0;i<p2.length;i++) out.print(p2[i]);
out.println();
int[] p12=suma(p1,p2);// pentru ca in teste rezultat = suma!
for(i=p12.length-1;i>=0;i--) out.print(p12[i]);
out.println();
out.close();
}//main
static void impare0() // cea mai mare cifra la mijloc
{
int i,k1,k2;
int imp1=nc1/2, imp2=nc2/2;
if(nc1%2==1) // numai daca nc1 si nc2 sunt impare !
for(i=9;i>=0;i--)
if(fc[i]>0)
{
p1[imp1]=i; fc[i]--;
354
}
static void impare1()
{
int i,k1,k2;
int imp1=nc1/2, imp2=nc2/2;
for(i=0;i<=9;i++)
if(fc[i]%2==1) { p1[imp1]=i; fc[i]--; break;}
for(i=0;i<=9;i++)
if(fc[i]%2==1) { p2[imp2]=i; fc[i]--; break;}
k1=0;
k2=0;
while(k1<nc1-nc2) {incarcPozitia(k1,p1); k1++;} // incarc numai p1
while((k1<imp1)||(k2<imp2))
{
if(k1<imp1) {incarcPozitia(k1,p1); k1++;}
if(k2<imp2) {incarcPozitia(k2,p2); k2++;}
}
}
static void impare2()
{
int i,k1,k2;
int imp1=nc1/2, imp2=nc2/2;
for(i=0;i<=9;i++)
if(fc[i]%2==1) { p1[imp1]=i; fc[i]--; break;}
for(i=0;i<=9;i++)
if(fc[i]%2==1) { p2[imp2]=i; fc[i]--; break;}
k1=0;
13.6. PAL
355
k2=0;
while(k1<nc1-nc2) {incarcPozitia(k1,p1); k1++;}// incarc numai p1
while((k1<imp1)||(k2<imp2))
{
if(k1<imp1) { incarcPozitia(k1,p1); k1++; }
if(k2<imp2) { incarcPozitia(k2,p2); k2++; }
}
}
static void corectez(int[] x)
{
int pozdif0,val, n=x.length;
pozdif0=0;
while(x[pozdif0]==0) pozdif0++;
if(pozdif0>0)
{
val=x[pozdif0];
x[0]=x[n-1]=val;
x[pozdif0]=x[n-pozdif0-1]=0;
}
}
static void incarcPozitia(int k, int[] x)
{
int i;
int n=x.length;
for(i=0;i<=9;i++)
if(fc[i]>0)
{
x[k]=i; fc[i]--;
x[n-k-1]=i; fc[i]--;
break;
}
}
static int[] suma(int[] x, int[] y)
{
int[] z=new int[(x.length>y.length) ? (x.length+1) : (y.length+1)];
int k,t=0;
for(k=0;k<=z.length-2;k++)
{
z[k]=t;
if(k<x.length) z[k]+=x[k];
if(k<y.length) z[k]+=y[k];
356
}
}//class
Capitolul 14
Factorial
autor
Pentru un num
ar natural nenul, definim factorialul s
au ca fiind produsul
tuturor numerelor naturale nenule mai mici sau egale decat el si l notam N !
(adica N ! = 1 2 ... N ). Pentru o baz
a de numeratie B si un num
ar natural
nenul N , se cere determinarea ultimei cifre nenule a scrierii n baza B a lui N !.
Cerint
a
Se citesc 5 perechi de forma (Ni , Bi ), unde 1 i 5. Pentru fiecare din
cele 5 perechi citite, aflati ultima cifra nenula a scrierii n baza Bi a factorialului
num
arului Ni .
Date de intrare
Fisierul de intrare fact.in contine 5 linii, pe fiecare dintre ele fiind scrise
cate dou
a numere naturale nenule Ni si Bi , scrise n baza 10, desp
artite printr-un
spatiu.
Date de iesire
Fisierul de iesire fact.out va contine 5 linii. Pe linia i se va afla cifra corespunzatoare unei perechi (Ni , Bi ), citita de pe linia i din fisierul de intrare.
Restrictii si preciz
ari
1 Ni 1000000, pentru 1 i 5;
2 Bi 36, pentru 1 i 5;
n cazul n care Bi > 10, cifrele mai mari decat 9 vor fi reprezentate prin
litere mari ale alfabetului englez (10 = A , 11 = B ,...,35 = Z );
un test va fi punctat doar dac
a toate cele 5 rezultate cerute sunt corecte.
357
358
Explicatie
5! = 120, n baza 10, deci ultima cifra nenula este 2
7! = 5040, n baza 10, deci ultima cifra nenula este 4
7! = CC0, n baza 20, deci ultima cifra nenula este C
8! = 9D80, n baza 16, deci ultima cifra nenula este 8
9! = 1304600, n baza 8, deci ultima cifra nenula este 6
14.1.1
Indicatii de rezolvare *
Solutia 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 fiecare dintre acestea se elimina
toti factorii primi ai lui B, retinuti n d[i][0]. Se pastreaza totodata n d[i][2] puterea
la care ar fi aparut acestia n descompunerea lui N !. Odat
a cu eliminarea factorilor
primi ai lui B din N !, se calculeaz
a si restul la mpartirea cu B al produsului (notat
p).
Se calculeaz
a apoi num
arul de zerouri consecutive care se vor afla 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 nmultite cu p si se fac aceste nmultiri moduloB. Acesta
este rezultatul cautat.
14.1.2
Rezolvare detaliat
a
14.1.3
Codul surs
a*
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)
14.1. FACTORIAL
359
{
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]; }
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")));
360
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
14.2
Limbaj
autor
Definim un limbaj de programare, cu instructiuni de atribuire si de decizie.
Sintaxa instructiunilor este:
Instructiunea de atribuire
variabila=variabila
Instructiunea de decizie
if
semn variabila variabila
{da
instructiuni }
{ nu
instructiuni }
fi
Variabilele limbajului sunt identificate printr-un singur caracter, litera mica,
din alfabetul englez. Valorile variabilelor sunt de tip ntreg.
semn este unul din caracterele < , > sau = .
Liniile instructiunilor nu contin spatii.
Instructiunile din { } pot lipsi.
Cerint
a
Daca se dau valorile initiale 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
executia secventei de program.
Date de intrare
Fisier de intrare: limbaj.in
Linia 1: Va Vb ... Vz - Valorile initiale ale variabilelor, de la a la z, separate
prin cate un spatiu.
361
14.2. LIMBAJ
14.2.1
Indicatii de rezolvare *
Solutia comisiei
Solutia problemei const
a n parcurgerea liniara a instructiunilor linie cu linie
si pastrarea valorilor logice ale conditiilor si respectiv a ramurilor da si nu ntr-un
sir.
362
Semnificatia pozitiei din sir este nivelul de imbricare la care ne aflam. Practic
parcurgem, far
a a evalua, acele instructiuni care nu apartin nivelului si ramurii pe
care ne aflam.
In acest sens vom evalua instructiunile de atribuire doar cele care ndeplinesc
conditiile de a se afla pe nivelul corespunzator si pentru care valorile conditiilor si
respectiv a ramurilor sunt n acealsi timp adevarate.
14.2.2
Rezolvare detaliat
a
14.2.3
Codul surs
a*
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];
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()
14.2. LIMBAJ
363
364
365
14.2. LIMBAJ
if(esteif()) blocif(ok);
System.out.println("
}// blocelem(...)
<-- blocelem:
"+s); //br.readLine();
366
{
14.2. LIMBAJ
367
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]===))
{
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(
368
14.3
Panouri
autor
Pe autostrada Soarele Estului sunt asezate de-a lungul soselei, la distante
egale, panouri publicitare ale unor firme. Aceeasi firma, poate s
a aiba mai multe
panouri publicitare si fiecare panou poate s
a apar
a n mai multe locuri. Panourile
se identifica prin numere naturale, num
arul total de panouri fiind N .
Firma X Corporation are panouri de T tipuri diferite. Firma a primit aprobarea 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 firmei, indiferent de ordinea acestora, si indiferent dac
a ntre ele se mai interpun
sau nu panouri ale altor firme.
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 firma, determinati
num
arul minim de intervale dintre dou
a panouri ntre care firma 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 firmei.
Date de iesire
369
14.3. PANOURI
panouri.out
2
Explicatie
Sunt N = 6 panouri : 1 2 3 5 3 1.
Firma are T = 2 tipuri de panouri: 5 si 1.
Cel mai scurt interval care contine elementele
5 si 1, este ntre panourile al 4 - lea
si al 6 -lea, si contine 2 intervale.
14.3.1
Indicatii de rezolvare *
Solutia comisiei
Reformulam problema: fiind dat un sir a[1..n] si o multime B cu m elemente,
s
a se gaseasca dou
a pozitii start si f inal, astfel ncat toate elementele multimii
B s
a fie continute n subsecventa a[start, ..., f inal], cu proprietatea ca diferenta
f inal start are valoare minima.
370
Cu alte cuvinte, s
a se gaseasca subsecventa de lungime minima a[start..f inal]
care contine toate elementele multimii B.
Avand n vedere valorile mici pentru tipurile de panouri (1 tip 1000),
pentru operatia de cautare n O(1) a unui element n multimea B, definim sirul
b[], cu b[i] = 1 dac
a i apartine multimii B.
Definim de asemenea srul frecventelor f r[], cu proprietatea ca f r[i] = x daca
i apartine lui B si i apare de x ori n subsecventa a[start, ..f inal].
Fixam start si f inal la valoarea 1 si increment
am pozitia f inal pana cand
toate elementele multimii B se afla n intervalul a[start, ..f inal]. Apoi incrementam
start pana la valoarea maxima la care a[start, ..f inal] mai contine nca toate
elementele multimii B.
In continuare, pentru fiecare incrementare a pozitiei f inal, marim cat se
poate de mult pozitia start, cu respectarea restrictiilor. In acest fel ne asiguram
ca pentru fiecare pozitie f inal, avem o subsecventa de lungime minima care contine
multimea B.
Algoritmul are complexitatea O(n).
14.3.2
Rezolvare detaliat
a
14.3.3
Codul surs
a*
Variant
a care depaseste timpul pentru ultimele 4 teste:
import java.io.*; // OK ... dar .. depasire timp executie pentru
class Panouri1
// t7=1.07sec t8=2.5sec t9=4.9sec t10=6.6sec
{
static int n,t,min;
static int[] x=new int[15001];
static int[] pf=new int[1001];
static int[] px=new int[1001];
static int[] pu=new int[1001];
static void calcul()
{
int i,j,npu,imin,jmin;
min=15123;
for(i=1;i<=n-t+1;i++)
{
imin=i;
if(pf[x[i]]==0) continue;
14.3. PANOURI
371
for(j=1;j<=1000;j++) pu[j]=0;
npu=1;
pu[x[i]]=1;
jmin=-1;
for(j=i+1;j<=n;j++)
{
if( (pf[x[j]]==1) && (pu[x[j]]==0) )
{
npu++;
pu[x[j]]=1;
if(npu==t) {jmin=j; break;}
}
}
if(npu==t)
if((jmin-imin)<min) min=jmin-imin;
}
}// calcul()
public static void main(String[] args) throws IOException
{
int i,tipp;
long t1,t2;
t1=System.currentTimeMillis();
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("panouri.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("panouri.out")));
st.nextToken(); n=(int)st.nval;
st.nextToken(); t=(int)st.nval;
for(i=1;i<=n;i++) { st.nextToken(); x[i]=(int)st.nval; px[x[i]]=1; }
for(i=1;i<=t;i++) { st.nextToken(); tipp=(int)st.nval; pf[tipp]=1; }
min=0;
for(i=1;i<=1000;i++)
if((px[i]==0)&&(pf[i]==1)) {min=-1; break;}
if(min==0)
if(t>1) calcul();
out.println(min);
out.close();
372
t2=System.currentTimeMillis();
System.out.println("Time = "+(t2-t1));
}// main(...)
}// class
Variant
a care se ncadreaz
a n timp pentru toate testele:
import java.io.*; // OK ... fara depasire timp executie pentru
class Panouri2
// t7=.13sec t8=0.15sec t9=0.18sec t10=0.19sec
{
static int n,t,min;
static int[] x=new int[15001];
static int[] pf=new int[1001]; // panou firma
static int[] px=new int[1001];
static int[] pu=new int[1001]; // panou utilizat
static void calcul()
{
int i,j,npu;
i=1;
while((i<=n)&&(pf[x[i]]==0)) i++; // i --> primul panou de firma
pu[x[i]]++;
// panou utilizat (nr de ori)
npu=1;
// nr panouri utilizate
j=i+1;
while((j<=n-t+1)&&(npu<t)) // ... toate panourile firmei ...
{
while(pf[x[j]]==0) j++;
if(pu[x[j]]==0) npu++;
pu[x[j]]++;
// panou utilizat (nr de ori)
if(npu<t) j++;
}
min=j-i;
// intre i ... j sunt toate ...
while(j<=n)
{
while(npu==t)
{
while(pf[x[i]]==0) i++; // i -->
if(pu[x[i]]==1) break; else {pu[x[i]]--; i++;}
}
if(j-i<min) min=j-i;
14.3. PANOURI
373
// il scot pe i ...
pu[x[i]]=0;
npu=t-1;
i++;
j++; // j --> pana refac nr panouri = t
while((j<=n)&&(npu<t))
{
while(pf[x[j]]==0) j++; // ma plasez pe panou firma
if(pu[x[j]]==0) npu++;
pu[x[j]]++;
// panou utilizat (nr de ori)
if(npu<t) j++;
}
}
}// calcul()
public static void main(String[] args) throws IOException
{
int i,tipp;
long t1,t2;
t1=System.currentTimeMillis();
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("panouri.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("panouri.out")));
st.nextToken(); n=(int)st.nval;
st.nextToken(); t=(int)st.nval;
for(i=1;i<=n;i++) { st.nextToken(); x[i]=(int)st.nval; px[x[i]]=1; }
for(i=1;i<=t;i++) { st.nextToken(); tipp=(int)st.nval; pf[tipp]=1; }
min=0;
for(i=1;i<=1000;i++)
if((px[i]==0)&&(pf[i]==1)) {min=-1; break;}
if(min==0)
if(t>1) calcul();
out.println(min);
out.close();
t2=System.currentTimeMillis();
System.out.println("Time = "+(t2-t1));
}// main(...)
}// class
374
14.4
Pereti
autor
Localitatea T
argoviste este n plina modernizare. Primaria decide s
a inventarieze toate cl
adirile din oras pentru a renova fatadele acestora. In acest sens
analizeaza harta orasului si constat
a ca toti peretii sunt asezati doar pe directia
Nord Sud sau Est Vest. Peretii vizibili de catre turisti sunt doar aceia la care se
poate ajunge din exteriorul orasului prin deplasarea pe cele dou
a directii date, n
oricare din cele 4 sensuri (N , E, S, V ). Harta orasului este ntocmit
a pe un caroiaj
format din patrate cu latura 1.
Cerint
a
Cunosc
andu-se harta orasului, determinati lungimea peretilor vizibili ce urmeaz
a a fi zugraviti.
Date de intrare
Fisierul de intrare pereti.in are pe prima linie dimensiunile m (num
arul de
linii), n (num
arul de coloane) ale hartii. Pe fiecare dintre urmatoarele m linii exista
n numere naturale de la 0 la 15, separate prin cate un spatiu, cu semnificatia:
- reprezentarea binar
a a num
arului pe 4 cifre semnific
a, ncepand de la stanga
spre dreapta, existenta unui perete spre directiile N , E, S, V (1 - exista
perete, 0 - nu exist
a perete; explicatii n figura de mai jos).
De exemplu valoarea 13 se reprezint
a n binar 1101, deci n mod corespunzator,
de la stanga spre dreapta, vom avea pereti spre N, E si V.
N
0
13 1
4 15
V
0 14
4 15
0 12
Date de iesire
Fisierul de iesire pereti.out va contine pe prima linie num
arul natural k
reprezent
and lungimea peretilor ce vor fi zugraviti.
Restrictii si preciz
ari
375
14.4. PERET
I
1 m, n 100
Peretii aflati la marginea hartii sunt pereti vizibili.
Datele de intrare sunt considerate corecte.
Exemplu
pereti.in
54
0 6 13 1
4 15 5 1
0 14 7 1
4 15 9 0
0 12 5 7
pereti.out
22
Explicatie
Pentru pozitiile (5, 2) si (5, 3) peretele dintre ele
va fi zugravit pe ambele fete.
Peretele dinspre Nord al pozitiei (1,3) este perete
exterior, chiar dac
a se afla pe marginea hartii.
14.4.1
Indicatii de rezolvare *
Solutia comisiei
Se bordeaza matricea cu valorile corespunzatoare, astfel ncat toata harta se
nconjor
a cu ziduri exterioare. Se determin
a toate pozitiile (celulele) din matrice
accesibile din pozitia (0, 0) care este exterioar
a astfel:
Se construieste un sir de perechi, (i, j) care vor marca pe r
and pozitiile din
matrice pe care le-am parcurs deja.
Se porneste din (0, 0), se determin
a toate pozitiile din matrice vecine cu
acestea, n care se poate ajunge, si se adauga la sirul construit. Odat
a adaugate,
se trece la urmatoarea pozitie din sir si se adauga din nou toti vecinii accesibili
din aceasta dar care nu figureaz
a n sirul nostru. Procedura continua pana cand
marcam toti vecinii celulelor adaugate n sir.
Pentru a marca elementele din matrice deja adaugate n sir adunam 16 fiecarei
celule. In acelasi timp adaugam num
arul de pereti vizibili din exterior, respectiv
1, 2 sau 3 n functie de valoarea celulei.
Verificarea vecinilor se realizeaza far
a a folosi descompunerea binara a valorilor. Se foloseste operatia AND ntre valorile numerice ntregi (de exemplu, 8 and
11 = 8 deci exist
a perete spre N).
14.4.2
Rezolvare detaliat
a
14.4.3
Codul surs
a*
376
import java.io.*;
class Pereti
{
static final int nord=8, est=4, sud=2, vest=1;
static int m,n,np,nz;
static int[][] a=new int[101][101];
static int[][] b=new int[101][101];
static void fill(int i, int j)
{
b[i][j]=nz;
if((a[i][j]
if((a[i][j]
if((a[i][j]
if((a[i][j]
&
&
&
&
nord)!=0)
est) !=0)
sud) !=0)
vest)!=0)
np++;
np++;
np++;
np++;
if((i-1>=1)&&(b[i-1][j]==0)&&((a[i][j]&nord)==0))
if((i+1<=m)&&(b[i+1][j]==0)&&((a[i][j]&sud)==0))
if((j-1>=1)&&(b[i][j-1]==0)&&((a[i][j]&vest)==0))
if((j+1<=n)&&(b[i][j+1]==0)&&((a[i][j]&est)==0))
}// fill(...)
fill(i-1,j);//
fill(i+1,j);//
fill(i,j-1);//
fill(i,j+1);//
np++;
np++;
np++;
np++;
//
//
//
//
vest
est
nord
sud
nord
sud
vest
est
14.5. SANT
377
14.5
S
ant
autor
Cei n detinuti ai unei nchisori, numerotati de la 1 la n, trebuie s
a sape un
sant dispus n linie dreapta ntre dou
a puncte A si B, situate la distanta de 250
km unul de celalalt, pe care exist
a 251 borne kilometrice numerotate de la 0 la
250. Fiecare detinut are ns
a o pretentie, e doar democratie, nu?: el doreste s
a
sape doar undeva n zona dintre borna x si borna y. Pe l
anga aceste pretentii
nchisoarea se confrunt
a si cu o alta problema: nu are suficienti paznici angajati.
Cerint
a
Cunosc
andu-se num
arul n de detinuti si pretentiile lor, s
a se determine locul
(locurile) unde vor fi pusi detinutii s
a sape ntr-o zi de munca, respectandu-se
pretentiile lor, astfel ncat num
arul de paznici necesari pentru a pazi cei n detinuti
s
a fie minim. Intervalul n care poate pazi un paznic nu poate contine dou
a sau
mai multe zone disjuncte dintre cele exprimate de detinuti n preferintele lor.
Date de intrare
Fisierul de intrare sant.in are pe prima linie num
arul n de detinuti. Pe fiecare
dintre urmatoarele n linii exist
a cate dou
a numere naturale, ai bi , separate printrun spatiu (ai bi ), care reprezint
a pretentia detinutului. Mai exact pe linia i + 1
(1 i n) este descrisa pretentia detinutului cu num
arul de ordine i.
Date de iesire
378
Explicatie
sunt necesari 2 paznici: paznicul 1 va pazi ntre
borna 8 si borna 13, iar detinutii paziti sunt 1 si 2;
paznicul 2 va pazi ntre borna 30 si borna 60, iar
detinutul pazit este 3
sunt necesari 3 paznici: paznicul 1 va pazi ntre
borna 10 si borna 20, iar detinutul pazit este 1;
paznicul 2 va pazi la borna 5, iar detinutii paziti
sunt 2 si 4; paznicul 3 va pazi ntre borna 30 si
borna 40, iar detinutul pazit este 3
14.5. SANT
14.5.1
379
Indicatii de rezolvare *
Solutia comisiei
Problema cere, de fapt, determinarea num
arului minim de intersectii ntre
segmentele determinate de kilometrul minim si maxim ntre care sap
a un detinut.
Pentru a le determina procedez astfel:
ordonez intervalele crescator dupa kilometrul minim si descrescator dupa
kilometrul maxim
pun primul detinut (deci cel cu intervalul de s
apare cel mai mare) n grija
primului paznic
pentru toate celelalte
caut un paznic care mai pazeste detinuti si care poate pazi si acest
detinut (adica intersectia segmentelor s
a fie nevida)
dac
a g
asesc
ajustez intervalul de s
apare ca s
a poat
a s
apa si acest detinut
altfel (daca nu g
asesc)
mai am nevoie de un paznic si l dau n grija acestuia
Datorit
a faptului ca intervalele sunt sortate, crescator dupa cap
atul inferior,
n momentul cand un interval nu se mai intersecteaza cu cel deja determinat, este
sigur ca nici un alt interval ce l urmeaz
a nu se mai intersecteaza, lucru ce asigura
determinarea num
arului minim de paznici.
14.5.2
Rezolvare detaliat
a
14.5.3
Codul surs
a*
import java.io.*;
class Sant
{
static int n;
static int[] x1=new int[10001];
static int[] x2=new int[10001];
static int[] o=new int[10001];
static void qsort(int li,int ls)
380
{
int val,aux,i,j;
i=li;
j=ls;
val=x2[(i+j)/2];
while(i<j)
{
while(x2[i]<val) i++;
while(x2[j]>val) j--;
if(i<=j)
{
aux=x1[i]; x1[i]=x1[j]; x1[j]=aux;
aux=x2[i]; x2[i]=x2[j]; x2[j]=aux;
aux=o[i]; o[i]=o[j];
o[j]=aux;
i++;
j--;
}
}// while
if(li<j) qsort(li,j);
if(i<ls) qsort(i,ls);
}// qsort(...)
public static void main(String[] args) throws IOException
{
int k,np,xp;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("sant.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("sant.out")));
st.nextToken(); n=(int)st.nval;
for(k=1;k<=n;k++)
{
st.nextToken(); x1[k]=(int)st.nval;
st.nextToken(); x2[k]=(int)st.nval;
o[k]=k;
}
qsort(1,n);
np=1;
381
14.6. ZUMZI
xp=x2[1];
for(k=2;k<=n;k++) if(x1[k]>xp) { np++; xp=x2[k]; }
out.println(np);
// inca o data pentru ...!
np=1;
xp=x2[1];
out.println(np+" "+xp+" "+xp);
out.print(o[1]+" ");
for(k=2;k<=n;k++)
{
if(x1[k]>xp)
{
out.println();
np++;
xp=x2[k];
out.println(np+" "+xp+" "+xp);
out.print(o[k]+" ");
}
else out.print(o[k]+" ");
}// for k
out.close();
}// main(...)
}// class
14.6
Zumzi
autor
Albinuta zumzi locuieste ntr-un stup format din N celule de forma hexagonal
a. Cele N celule numerotate de la 1 la N sunt dispuse sub forma de spiral
a
(ca n figura).
15
16
14
13
12
3
11
10
18
7
8
9
23
17
19
20
21
22
382
383
14.6. ZUMZI
Exemplu
zumzi.in
12 4 3 9
11 4 6 8
12 4 4 2
11 4 6 8
zumzi.out
4
Explicatie
Variantele sunt:
5
4
6
1-2-10-9
12
1
3
7
1-3-2-9
2
11
10
8
1-3-10-9
9
1-7-2-9
Variantele avute la dispozitie sunt:
1-3-10-9-2
1-7-1-3-2
1-5-1-7-2
etc.
14.6.1
Indicatii de rezolvare *
Solutia comisiei
Pentru memorarea stupului vom folosi o matrice patratica T de ordinul
2 k + 1, unde valoarea lui k este data de relatia:
3 (k 1) k + 1 < n 3 k (k + 1) + 1
adica k reprezint
a num
arul de cercuri concentrice din stup (far
a a num
ara celula
1 ca un cerc).
T [k + 1, k + 1] = 1 adica reprezint
a celula din centrul stupului.
Celulele vecine ale celulei de la coordonatele (i, j) din matricea T vor fi, n
ordine:
(i + 1, j), (i + 1, j 1), (i, j 1), (i 1, j), (i 1, j + 1), (i, j + 1).
De exemplu pentru N = 12 matricea T va ar
ata astfel:
0 0
0 0
0 4
12 3
11 10
0
5
1
2
9
0
6
7
8
0
0
0
0
0
0
384
13 4 1 7 19
12 3 2 8 20
11 10 9 21 0
24 23 22 0 0
0
0
0
0
14.6.2
Rezolvare detaliat
a
0,1
0,0
0,3
0,5
0,2
0,4
1,1
1,3
1,0
2,0
1,4
2,3
3,3
4,0
4,3
3,6
4,4
i-1, j
N
i-(j%2) , j-1
NV
NE
i-(j%2) , j+1
i,j
i+1-(j%2) , j-1
SV
SE
S
i+1, j
3,7
4,5
4,2
2,8
2,6
3,4
4,1
2,7
3,5
3,2
1,8
1,6
2,4
3,1
0,8
1,7
2,5
2,2
3,0
0,6
1,5
1,2
2,1
0,7
i+1-(j%2) , j+1
3,8
4,7
4,6
4,8
385
14.6. ZUMZI
14.6.3
Codul surs
a*
Variant
a far
a numere mari:
import java.io.*;
class Zumzi1
{
static int n,m,np,x;
static int nv=0,nc=0;
static
static
static
static
// np=nr pasi
// stup
// pozitie in stup: linia
// pozitie in stup: coloana
// centrul stupului
static
static
static
static
int
int
int
int
in(int
jn(int
is(int
js(int
j)
j)
j)
j)
{
{
{
{
static
static
static
static
int
int
int
int
ine(int
jne(int
ise(int
jse(int
i,int
i,int
i,int
i,int
j)
j)
j)
j)
{
{
{
{
static
static
static
static
int
int
int
int
inv(int
jnv(int
isv(int
jsv(int
i,int
i,int
i,int
i,int
j)
j)
j)
j)
{
{
{
{
return
return
return
return
i-1;
j;
i+1;
j;
}
}
}
}
//
//
//
//
i
j
i
j
nord
nord
sud
sud
return
return
return
return
i-j%2;
j+1;
i+1-j%2;
j+1;
}
}
}
}
//
//
//
//
i
j
i
j
nord_est
nord_est
sud_est
sud_est
return
return
return
return
i-j%2;
j-1;
i+1-j%2;
j-1;
}
}
}
}
//
//
//
//
i
j
i
j
nord_vest
nord_vest
sud_vest
sud_vest
386
387
14.6. ZUMZI
{
ic=i; jc=j;
i=ise(ic,jc); j=jse(ic,jc);
s[i][j]=++k; is[k]=i; js[k]=j;
}
if(k==n) break;
// sud nc pasi
for(np=1;np<=nc&&k<n;np++)
{
ic=i; jc=j;
i=is(ic,jc); j=js(ic,jc);
s[i][j]=++k; is[k]=i; js[k]=j;
}
}// while
}// stupul()
static void calcul()
{
int i,k,v;
nd[1][0]=1;
for(k=1;k<=np;k++)
{
for(i=1;i<=n;i++)
{
nd[i][k%2]=0;
// v=vecin
// zumzi
// pasul k
// celula i
// este suma vecinilor
if(a[i]==1) continue;
if((i==x)&&(k<np)) continue;
// este ocupata
// nu mai pleaca !
// vecin la nord_est
// celula libera
v=s[ise(is[i],js[i])][jse(is[i],js[i])];
if(a[v]==0) nd[i][k%2]+=nd[v][(k+1)%2];
// vecin la sud_est
// celula libera
v=s[inv(is[i],js[i])][jnv(is[i],js[i])];
if(a[v]==0) nd[i][k%2]+=nd[v][(k+1)%2];
// vecin la nord_vest
// celula libera
388
v=s[isv(is[i],js[i])][jsv(is[i],js[i])];
if(a[v]==0) nd[i][k%2]+=nd[v][(k+1)%2];
}// for i
}// for k
}// calcul()
// vecin la sud_vest
// celula libera
// numerotare celule
out.println(nd[x][np%2]);
out.close();
}// main(...)
}// class
Variant
a cu numere mari:
import java.io.*; // test2 = ? aici = 18697967389042507036635337140
class Zumzi2
// in 2-zumzi.ok = 18709929980883486610943359969
{
static int n,m,np,xz; // np=nr pasi
static int nv=0,nc=0;
static
static
static
static
// nr drumuri
389
14.6. ZUMZI
static int i0=11, j0=11;
i,int
i,int
i,int
i,int
// centrul stupului
static
static
static
static
int
int
int
int
in(int
jn(int
is(int
js(int
j)
j)
j)
j)
{
{
{
{
static
static
static
static
int
int
int
int
ine(int
jne(int
ise(int
jse(int
i,int
i,int
i,int
i,int
j)
j)
j)
j)
{
{
{
{
static
static
static
static
int
int
int
int
inv(int
jnv(int
isv(int
jsv(int
i,int
i,int
i,int
i,int
j)
j)
j)
j)
{
{
{
{
return
return
return
return
i-1;
j;
i+1;
j;
}
}
}
}
//
//
//
//
i
j
i
j
nord
nord
sud
sud
return
return
return
return
i-j%2;
j+1;
i+1-j%2;
j+1;
}
}
}
}
//
//
//
//
i
j
i
j
nord_est
nord_est
sud_est
sud_est
return
return
return
return
i-j%2;
j-1;
i+1-j%2;
j-1;
}
}
}
}
//
//
//
//
i
j
i
j
nord_vest
nord_vest
sud_vest
sud_vest
390
// sud nc pasi
for(np=1;np<=nc&&k<n;np++)
{
ic=i; jc=j;
i=is(ic,jc); j=js(ic,jc);
s[i][j]=++k; is[k]=i; js[k]=j;
}
}// while
}// stupul()
391
14.6. ZUMZI
static int[] nrv(int nr)
{
int[] x;
if(nr==0) { x=new int[1]; x[0]=0; }
else
{
int nc, nrrez=nr;
nc=0;
while(nr!=0) {nc++; nr=nr/10;}
x=new int[nc];
nr=nrrez;
nc=0;
while(nr!=0) { x[nc]=nr%10; nc++; nr=nr/10;}
}
return x;
}// nrv(...)
// v=vecin
// zumzi
392
// pasul k
// celula i
// este suma vecinilor
if(a[i]==1) continue;
if((i==xz)&&(k<np)) continue;
// este ocupata
// nu mai pleaca !
v=s[in(is[i],js[i])][jn(is[i],js[i])];
// vecin la nord
if(a[v]==0) nd[i][k%2]=suma(nd[i][k%2],nd[v][(k+1)%2]);
v=s[is(is[i],js[i])][js(is[i],js[i])];
// vecin la sud
if(a[v]==0) nd[i][k%2]=suma(nd[i][k%2],nd[v][(k+1)%2]);
v=s[ine(is[i],js[i])][jne(is[i],js[i])];
// vecin la nord_est
if(a[v]==0) nd[i][k%2]=suma(nd[i][k%2],nd[v][(k+1)%2]);
v=s[ise(is[i],js[i])][jse(is[i],js[i])];
// vecin la sud_est
if(a[v]==0) nd[i][k%2]=suma(nd[i][k%2],nd[v][(k+1)%2]);
v=s[inv(is[i],js[i])][jnv(is[i],js[i])];
// vecin la nord_vest
if(a[v]==0) nd[i][k%2]=suma(nd[i][k%2],nd[v][(k+1)%2]);
v=s[isv(is[i],js[i])][jsv(is[i],js[i])];
// vecin la sud_vest
if(a[v]==0) nd[i][k%2]=suma(nd[i][k%2],nd[v][(k+1)%2]);
}// for i
}// for k
}// calcul()
public static void main(String[] args) throws IOException
{
int i,j;
StreamTokenizer st=new StreamTokenizer(
new BufferedReader(new FileReader("zumzi.in")));
PrintWriter out=new PrintWriter(
new BufferedWriter(new FileWriter("zumzi.out")));
st.nextToken(); n=(int)st.nval;
st.nextToken(); m=(int)st.nval;
st.nextToken(); np=(int)st.nval;
st.nextToken(); xz=(int)st.nval;
for(i=1;i<=m;i++)
393
14.6. ZUMZI
stupul();
calcul();
// numerotare celule
for(i=nd[xz][np%2].length-1;i>=0;i--) out.print(nd[xz][np%2][i]);
out.println();
out.close();
}// main(...)
}// class