#include <bits/stdc++.h>
using namespace std;
int n, dopisano[200111], dl[200111];
long long t[200111];
long long wynik;
int liczbaCyfr(long long w) {
int res = 0;
while(w > 0) {
res++;
w /= 10;
}
return res;
}
int aktWiekszaLeksy(long long pop, long long akt) {
vector<int> vPop, vAkt;
while(pop > 0) {
vPop.push_back(pop%10);
pop /= 10;
}
while(akt > 0) {
vAkt.push_back(akt%10);
akt /= 10;
}
while(!vPop.empty() && !vAkt.empty()) {
if(vPop.back() > vAkt.back()) return -1; //poprzednia leksykograficznie wieksza
if(vPop.back() < vAkt.back()) return 1; //aktualna leksykograficznie wieksza
vPop.pop_back();
vAkt.pop_back();
}
return 0; //aktualna prefixem poprzedniej
}
void dopiszZera(int in, int doDopisania) {
long long akt = t[in];
dopisano[in] = doDopisania;
int lc = liczbaCyfr(akt);
while(doDopisania > 0) {
if(lc < 17) {
akt *= 10;
lc++;
}
else {
dl[in] = doDopisania;
break;
}
doDopisania--;
}
t[in] = akt;
}
bool nieSameDziewiatki(int in) {
int ileMogeZmienic = liczbaCyfr(t[in]) - liczbaCyfr(t[in+1]);
long long liczba = t[in];
if(ileMogeZmienic > 15) ileMogeZmienic = 15;
while(ileMogeZmienic > 0) {
if(liczba%10 < 9) return true;
ileMogeZmienic--;
liczba /= 10;
}
return false;
}
void dopiszWieksze(int in) {
int ileDopisano = liczbaCyfr(t[in-1]) - liczbaCyfr(t[in]) + dl[in-1];
long long liczba = t[in-1];
liczba++;
t[in] = liczba;
dl[in] = dl[in-1]; //tyle samo zer powyżej ~10^18
dopisano[in] = ileDopisano;
}
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%lld", &t[i]);
}
for(int i = 2; i <= n; i++) {
int lcl = liczbaCyfr(t[i-1]), lca = liczbaCyfr(t[i]);
if(lcl < lca) { //aktualna liczba jest dłuższa od poprzedniej, więc jest większa
continue;
}
if(lcl == lca) { //aktualna liczba jest równie długa co poprzednia
if(t[i] > t[i-1]) { //aktualna liczba jest większa od poprzedniej, zostawiam
continue;
}
if(t[i] <= t[i-1]) { //aktualna liczba jest mniejsza lub równa poprzedniej
t[i] *= 10;
dopisano[i] = 1;
continue;
}
}
//aktualna liczba jest krótsza niż poprzednia
int leks = aktWiekszaLeksy(t[i-1], t[i]);
if(leks == 1) { //aktualna jest leksykograficznie większa, wypełniam zerami do równej długości
int doDopisania = lcl - lca + dl[i-1];
dopiszZera(i, doDopisania);
continue;
}
if(leks == 0) { //aktualna jest prefiksem poprzedniej,
if(nieSameDziewiatki(i-1)) { //jeśli dopisane do poprzedniej cyfry są różne od dziewiątek, to zwiększam
dopiszWieksze(i);
}
else { //w przeciwnym wypadku dodaję same zera aby uzyskać dłuższą liczbę
int doDopisania = lcl - lca + dl[i-1] + 1;
dopiszZera(i, doDopisania);
}
continue;
}
//aktualna jest leksykograficznie mniejsza, wypełniam zerami żeby była dłuższa o 1
int doDopisania = lcl - lca + dl[i-1] + 1;
dopiszZera(i, doDopisania);
}
for(int i = 1; i <= n; i++) wynik += dopisano[i];
printf("%lld\n", wynik);
}
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | #include <bits/stdc++.h> using namespace std; int n, dopisano[200111], dl[200111]; long long t[200111]; long long wynik; int liczbaCyfr(long long w) { int res = 0; while(w > 0) { res++; w /= 10; } return res; } int aktWiekszaLeksy(long long pop, long long akt) { vector<int> vPop, vAkt; while(pop > 0) { vPop.push_back(pop%10); pop /= 10; } while(akt > 0) { vAkt.push_back(akt%10); akt /= 10; } while(!vPop.empty() && !vAkt.empty()) { if(vPop.back() > vAkt.back()) return -1; //poprzednia leksykograficznie wieksza if(vPop.back() < vAkt.back()) return 1; //aktualna leksykograficznie wieksza vPop.pop_back(); vAkt.pop_back(); } return 0; //aktualna prefixem poprzedniej } void dopiszZera(int in, int doDopisania) { long long akt = t[in]; dopisano[in] = doDopisania; int lc = liczbaCyfr(akt); while(doDopisania > 0) { if(lc < 17) { akt *= 10; lc++; } else { dl[in] = doDopisania; break; } doDopisania--; } t[in] = akt; } bool nieSameDziewiatki(int in) { int ileMogeZmienic = liczbaCyfr(t[in]) - liczbaCyfr(t[in+1]); long long liczba = t[in]; if(ileMogeZmienic > 15) ileMogeZmienic = 15; while(ileMogeZmienic > 0) { if(liczba%10 < 9) return true; ileMogeZmienic--; liczba /= 10; } return false; } void dopiszWieksze(int in) { int ileDopisano = liczbaCyfr(t[in-1]) - liczbaCyfr(t[in]) + dl[in-1]; long long liczba = t[in-1]; liczba++; t[in] = liczba; dl[in] = dl[in-1]; //tyle samo zer powyżej ~10^18 dopisano[in] = ileDopisano; } int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%lld", &t[i]); } for(int i = 2; i <= n; i++) { int lcl = liczbaCyfr(t[i-1]), lca = liczbaCyfr(t[i]); if(lcl < lca) { //aktualna liczba jest dłuższa od poprzedniej, więc jest większa continue; } if(lcl == lca) { //aktualna liczba jest równie długa co poprzednia if(t[i] > t[i-1]) { //aktualna liczba jest większa od poprzedniej, zostawiam continue; } if(t[i] <= t[i-1]) { //aktualna liczba jest mniejsza lub równa poprzedniej t[i] *= 10; dopisano[i] = 1; continue; } } //aktualna liczba jest krótsza niż poprzednia int leks = aktWiekszaLeksy(t[i-1], t[i]); if(leks == 1) { //aktualna jest leksykograficznie większa, wypełniam zerami do równej długości int doDopisania = lcl - lca + dl[i-1]; dopiszZera(i, doDopisania); continue; } if(leks == 0) { //aktualna jest prefiksem poprzedniej, if(nieSameDziewiatki(i-1)) { //jeśli dopisane do poprzedniej cyfry są różne od dziewiątek, to zwiększam dopiszWieksze(i); } else { //w przeciwnym wypadku dodaję same zera aby uzyskać dłuższą liczbę int doDopisania = lcl - lca + dl[i-1] + 1; dopiszZera(i, doDopisania); } continue; } //aktualna jest leksykograficznie mniejsza, wypełniam zerami żeby była dłuższa o 1 int doDopisania = lcl - lca + dl[i-1] + 1; dopiszZera(i, doDopisania); } for(int i = 1; i <= n; i++) wynik += dopisano[i]; printf("%lld\n", wynik); } |
English