#include <stdio.h> #include <string.h> int cyfr(long int i) { int rv=0; while (i>0) { i/=10; rv++; } rv++; return rv; } class Liczba { // liczba w postaci a * 10^n + r char *mCyfra; int mCyfr; public: int IleCyfr() { return mCyfr; } Liczba(FILE *f) { mCyfra = new char[200100]; Load(f); } void Load(FILE *f) { fgets(mCyfra, 200100, f); mCyfr = 0; while(mCyfra[mCyfr]>='0' && mCyfra[mCyfr]<='9') { mCyfr++; } mCyfra[mCyfr] = 0; } Liczba(const char *s) { mCyfra = new char[200100]; mCyfr = 0; while(s[mCyfr]>='0' && s[mCyfr]<='9') { mCyfra[mCyfr] = s[mCyfr]; mCyfr++; } mCyfra[mCyfr] = 0; } ~Liczba() { delete mCyfra; } bool operator<(const Liczba &b) { if (b.mCyfr > mCyfr) { return true; } if (b.mCyfr < mCyfr) { return false; } else { // ilosc cyfr sie zgadza return strcmp(mCyfra, b.mCyfra) < 0; } return true; } // NOTICE: to nie jest poprawny operator =, bo niszczy b Liczba &operator=(Liczba &b) { char *t = mCyfra; mCyfra = b.mCyfra; b.mCyfra = t; mCyfr = b.mCyfr; return *this; } int porownajPrefix(const Liczba &min) { return strncmp(mCyfra, min.mCyfra, mCyfr); // nasza cyfra na pewno nie ma wiecej cyfr niz min, bo by byla wieksza } long int dopelnijZerami(int ileMaBycCyfr) { long int nowych = ileMaBycCyfr; nowych -= mCyfr; memset(mCyfra + mCyfr, '0', ileMaBycCyfr - mCyfr); mCyfr = ileMaBycCyfr; mCyfra[mCyfr] = 0; return nowych; } long int zwiekszMinimalnie(int poczatek) { long int nowych = mCyfr; nowych -= poczatek; int propozycja = -1; while (mCyfra[poczatek]) { if (mCyfra[poczatek] < '9') { // szukamy ostatniej, ktora jest mniejsza niz 9 propozycja = poczatek; } poczatek++; } if (propozycja < 0) { // niestety, nie dalo sie mCyfra[mCyfr]='0'; mCyfr++; nowych++; } else { mCyfra[propozycja]++; // zwiekszamy ostatnia propozycje } return nowych; } void print() { puts(mCyfra); } }; int main() { int i; int n; Liczba min("0"); Liczba a("0"); long int rv = 0; scanf("%d\n", &n); for(i=0;i<n;i++) { a.Load(stdin); //Liczba a(stdin); if (min<a) { min=a; } else { //min.print(); // debugowanie oczywiscie printem ;-) //a.print(); int c = a.porownajPrefix(min); if (c<0) { // prefix nowej liczby jest mniejszy niz prefix minimum, czyli np minimum to 80, a nowa liczba to 3 rv += a.dopelnijZerami(min.IleCyfr() + 1); min = a; } else if (c==0) { // prefixy sa takie same // jesli prefixy sa takie same, to trzeba sprawdzic, czy da sie zwiekszyc jakas cyfre, bo moze nie trzeba rv += min.zwiekszMinimalnie(a.IleCyfr()); } else { // prefix nowej liczby jest wiekszy niz prefix minimum, czyli dopelniamy zerami rv += a.dopelnijZerami(min.IleCyfr()); min = a; } } } printf("%ld\n", rv); return 0; }
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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | #include <stdio.h> #include <string.h> int cyfr(long int i) { int rv=0; while (i>0) { i/=10; rv++; } rv++; return rv; } class Liczba { // liczba w postaci a * 10^n + r char *mCyfra; int mCyfr; public: int IleCyfr() { return mCyfr; } Liczba(FILE *f) { mCyfra = new char[200100]; Load(f); } void Load(FILE *f) { fgets(mCyfra, 200100, f); mCyfr = 0; while(mCyfra[mCyfr]>='0' && mCyfra[mCyfr]<='9') { mCyfr++; } mCyfra[mCyfr] = 0; } Liczba(const char *s) { mCyfra = new char[200100]; mCyfr = 0; while(s[mCyfr]>='0' && s[mCyfr]<='9') { mCyfra[mCyfr] = s[mCyfr]; mCyfr++; } mCyfra[mCyfr] = 0; } ~Liczba() { delete mCyfra; } bool operator<(const Liczba &b) { if (b.mCyfr > mCyfr) { return true; } if (b.mCyfr < mCyfr) { return false; } else { // ilosc cyfr sie zgadza return strcmp(mCyfra, b.mCyfra) < 0; } return true; } // NOTICE: to nie jest poprawny operator =, bo niszczy b Liczba &operator=(Liczba &b) { char *t = mCyfra; mCyfra = b.mCyfra; b.mCyfra = t; mCyfr = b.mCyfr; return *this; } int porownajPrefix(const Liczba &min) { return strncmp(mCyfra, min.mCyfra, mCyfr); // nasza cyfra na pewno nie ma wiecej cyfr niz min, bo by byla wieksza } long int dopelnijZerami(int ileMaBycCyfr) { long int nowych = ileMaBycCyfr; nowych -= mCyfr; memset(mCyfra + mCyfr, '0', ileMaBycCyfr - mCyfr); mCyfr = ileMaBycCyfr; mCyfra[mCyfr] = 0; return nowych; } long int zwiekszMinimalnie(int poczatek) { long int nowych = mCyfr; nowych -= poczatek; int propozycja = -1; while (mCyfra[poczatek]) { if (mCyfra[poczatek] < '9') { // szukamy ostatniej, ktora jest mniejsza niz 9 propozycja = poczatek; } poczatek++; } if (propozycja < 0) { // niestety, nie dalo sie mCyfra[mCyfr]='0'; mCyfr++; nowych++; } else { mCyfra[propozycja]++; // zwiekszamy ostatnia propozycje } return nowych; } void print() { puts(mCyfra); } }; int main() { int i; int n; Liczba min("0"); Liczba a("0"); long int rv = 0; scanf("%d\n", &n); for(i=0;i<n;i++) { a.Load(stdin); //Liczba a(stdin); if (min<a) { min=a; } else { //min.print(); // debugowanie oczywiscie printem ;-) //a.print(); int c = a.porownajPrefix(min); if (c<0) { // prefix nowej liczby jest mniejszy niz prefix minimum, czyli np minimum to 80, a nowa liczba to 3 rv += a.dopelnijZerami(min.IleCyfr() + 1); min = a; } else if (c==0) { // prefixy sa takie same // jesli prefixy sa takie same, to trzeba sprawdzic, czy da sie zwiekszyc jakas cyfre, bo moze nie trzeba rv += min.zwiekszMinimalnie(a.IleCyfr()); } else { // prefix nowej liczby jest wiekszy niz prefix minimum, czyli dopelniamy zerami rv += a.dopelnijZerami(min.IleCyfr()); min = a; } } } printf("%ld\n", rv); return 0; } |