Fermierul Feder cultivă cartofi pe un teren dreptunghiular de lățime N metri și lungime M metri, compartimentat în N * M zone pătratice identice de lungime 1 metru, dispuse alăturat, câte N pe lățime (pe N linii, numerotate de la 1 la N) și câte M pe lungime (pe M coloane, numerotate de la 1 la M).
În fiecare zonă pătratică se află câte o plantă de cartofi. Parcurgând terenul de la prima linie către ultima, fiecare linie cu număr impar parcurgând-o de la coloana 1 către coloana M, iar fiecare linie cu număr par parcurgând-o de la coloana M către coloana 1, fermierul (pasionat de matematică) a scris numerele cartofilor produși de fiecare plantă, în ordinea parcurgerii, și a constatat că a obținut șirul cifrelor unităților primilor N * M termeni ai șirului Fibonacci (vezi Figura 1 în care N = 3 și M = 6).
Cerința
Scrieți un program care citește numerele N și M (cu semnificația din enunț), iar apoi determină:
1. numărul plantelor din teren care nu au produs niciun cartof;
2. numărul maxim de cartofi care pot fi produși de plantele dintr-o suprafață pătratică din terenul fermierului;
3. pentru fiecare dintre cele Q perechi de numere (A, B) citite, numărul cartofilor produși de plantele aflate în zonele pătratice situate între coloanele cu numerele A și B, inclusiv acestea.
Date de intrare
Fișierul de intrare cartofi.in conține pe prima linie un număr natural C reprezentând cerința din problemă care trebuie rezolvată (1, 2 sau 3). A doua linie a fișierului conține cele două numere naturale N și M, separate printr-un spațiu, cu semnificația din enunț. Dacă C = 3, atunci fișierul va mai conține pe a treia linie numărul natural Q, iar pe fiecare linie dintre următoarele Q, câte două numere naturale separate printr-un spațiu reprezentând câte o pereche de numere (A, B) dintre cele Q.
Date de ieșire
Fișierul de ieșire cartofi.out va conține:
- Dacă
C = 1, pe prima linie un număr natural reprezentând răspunsul la cerința1. - Dacă
C = 2, pe prima linie un număr natural reprezentând răspunsul la cerința2. - Dacă
C = 3,Qlinii, câte o linie pentru fiecare pereche(A, B)dintre celeQ. Linia corespunzătoare fiecărei perechi(A, B)va conține un număr natural reprezentând numărul cartofilor produși de plantele aflate în zonele pătratice situate între coloanele cu numereleAșiB, inclusiv aceste valori, reprezentând răspunsul la cerința3.
Restricții și precizări
2 ≤ N ≤ 500.000.0003 ≤ M ≤ 1.000.000.000N ≤ MQ ≤ 100.0001 ≤ A ≤ B ≤ M- Pentru cerința 1 se acordă 20p, iar pentru cerințele 2 și 3 se acordă câte 40p.
- Șirul Fibonacci este definit astfel:
f(1) = 1,f(2) = 1șif(n) = f(n-1) + f(n-2), dacăn ≥ 3, (neste un număr natural nenul). - O suprafață pătratică din teren este formată din
K * Kzone pătratice alăturate dispuse câteKpe linie și câteKpe coloană, oricare ar fi1 ≤ K ≤ min{N, M}.
Exemplul 1:
cartofi.in
1 3 6
cartofi.out
1
Explicație
Se rezolvă cerința 1. N = 3, M = 6. Primii N * M = 18 termeni ai șirului Fibonacci sunt: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584. Astfel, numerele cartofilor produși de fiecare plantă din teren sunt cele din Figura 1. În teren există o singură plantă care nu a produs niciun cartof (cea din linia 3, coloana 3).
Exemplul 2:
cartofi.in
2 3 6
cartofi.out
42
Explicație
Se rezolvă cerința 2. N = 3, M = 6. Numerele cartofilor produși de fiecare plantă din teren sunt cele din tabelul din Figura 1. Plantele aflate în suprafața pătratică galbenă din tabelul din Figura 2 au produs cel mai mare număr de cartofi.
Exemplul 3:
cartofi.in
3 5 6 3 1 2 4 6 2 3
cartofi.out
48 64 43
Explicație
Se rezolvă cerința 3. N = 5, M = 6, Q = 3. Tabelul din Figura 3 conține numerele cartofilor produși de fiecare plantă din teren sunt cele din Figura 3. Suma elementelor cuprinse între coloanele (1, 2), inclusiv 1 și 2, este 48. Suma elementelor cuprinse între coloanele (4, 6), inclusiv 4 și 6, este 64. Suma elementelor cuprinse între coloanele (2, 3), inclusiv 2 și 3, este 43.
#include <bits/stdc++.h>
using namespace std;
ifstream f("cartofi.in");
ofstream g("cartofi.out");
pair<int, int> fibo(long long n)
{
if (n == 0)
return {0, 1};
auto p = fibo(n >> 1ll);
int ax = ((p.second << 1) - p.first + 10) % 10;
int c = (p.first * ax) % 10;
int d = (p.first * p.first + p.second * p.second) % 10;
if (n & 1)
return {d, (c + d) % 10};
return {c, d}; }
int n, m;
long long cols[61];
long long query(int);
void build();
void solve1();
void solve2();
void solve3();
int32_t main()
{
int task;
f >> task >> n >> m;
if (task == 1)
solve1();
else if (task == 2)
solve2();
else
solve3();
return 0;
}
void solve1()
{
long long ct = 0, ax = (1ll * n * m) / 60ll, ap = (1ll * n * m) % 60ll;
long long rez = 0;
for (int i = 0, a = 0, b = 1, c; i < 60; i++)
{
ct += !b;
if (i < ap)
rez += !b;
c = (a + b) % 10;
a = b;
b = c;
}
rez += 1ll * ax * ct;
g << rez;
}
void solve2()
{
build();
long long rez = 0, ax;
for (int i = n; i <= min(n + 60, m); i++)
{
ax = query(i) - query(i - n);
rez = max(rez, ax);
}
g << rez;
}
void solve3()
{
build();
int q, st, dr;
for (f >> q; q; q--)
{
f >> st >> dr;
g << (long long)query(dr) - query(st - 1) << '\n';
}
}
void build()
{
long long aux[61], prv = 0, md = n % 60, ct = n / 60, ind;
memset(aux, 0, sizeof aux);
for (int i = 0, nr; i < min(n, 60); i++, prv += m)
for (int j = 1; j <= min(m, 60); j++)
{
ind = prv;
if (i & 1)
ind += m - j + 1;
else
ind += j;
nr = fibo(ind).first;
cols[j] += nr;
if (i < md)
aux[j] += nr;
}
for (int i = 1; i <= min(m, 60); i++)
cols[i] = 1ll * cols[i] * ct + aux[i], cols[i] += cols[i - 1];
}
long long query(int poz)
{
long long rez = 1ll * (poz / 60) * cols[60];
rez += cols[poz % 60];
return rez;
}