Rezolvare completă PbInfo #2438 pal

Micul Prinț a ajuns în țara numerelor palindrom cu număr impar de cifre unde a primit de la sfetnicul regelui o listă care conține N numere naturale, fiecare cu număr impar de cifre. Un număr este palindrom dacă prima lui cifră este egală cu ultima, a doua cu penultima, ș.a.m.d. Acesta i-a transmis că regele este foarte bolnav. Odată cu regele, numerele din listă s-au îmbolnăvit și ele. Sfetnicul i-a spus că lista corectă poate fi obținută prin înlocuirea fiecărui număr din ea cu cel mai mic palindrom mai mare sau egal cu numărul respectiv.
După ce a urmat recomandarea sfetnicului, Micul Prinț a constatat că în lista corectă obținută toate palindromurile sunt distincte. Uitându-se mai cu atenție la palindromurile din această listă, a observat că există perechi de palindromuri în care cel mai mic se poate obține din cel mai mare prin ștergerea aceluiași număr de cifre de la ambele capete. De exemplu pentru perechea 7531357 și 313 palindromul 313 se obține din 7531357 prin eliminarea a câte două cifre de la ambele capete ale sale.
Considerăm un șir de palindromuri din lista corectă și notăm cu X valoarea maximă a acestui șir. Vom spune că șirul este magic dacă toate palindromurile din el se pot obține după metoda descrisă mai sus, din palindromul de valoare X. Un exemplu de șir magic este 4, 53435, 7534357, 89753435798, presupunând că toate aceste numere se regăsesc în lista corectă.

Cerința

Scrieți un program care citește numerele din lista primită de la sfetnicul regelui și afișează:
1) Lista corectă obținută de Micul Prinț;
2) Numărul de elemente ale celui mai lung șir magic care se poate obține din lista corectă;
3) Palindromurile din care este format cel mai lung șir magic, afișate în ordine crescătoare. Dacă există mai multe astfel de șiruri în lista corectă a Micului Prinț, se va afișa cel în care ultimul număr este cel mai mare.

Date de intrare

Fișierul de intrare pal.in conţine pe prima linie numărul natural P, care nu poate avea decât valorile 1, 2 sau 3 și indică numărul cerinței care va fi rezolvată. Pe a doua linie numărul natural N de numere de pe lista primită de la sfetnicul regelui. Pe a treia linie se află numerele naturale din lista primită de la sfetnic, separate prin câte un spațiu.

Date de ieșire

Fișierul de ieșire pal.out va conţine pe prima linie răspunsul la cerința rezolvată. Dacă s-a rezolvat prima cerință, fișierul de ieșire va conține un șir de N numere naturale, separate prin câte un spațiu, reprezentând numerele din lista corectă, în ordinea corespunzătoare listei inițiale. Dacă s-a rezolvat cerința 2, pe prima linie a fișierului de ieșire se va scrie lungimea celui mai lung șir magic. Dacă s-a rezolvat cerința 3, fișierul de ieșire va conține numerele determinate și afișate conform cerinței.

Restricții și precizări

  • 0 < N ≤ 50000;
  • Numerele de pe lista sfetnicului sunt naturale nenule și fiecare are cel mult 17 cifre;
  • Pentru rezolvarea corectă a primei cerinţe se acordă 20 de puncte, pentru rezolvarea corectă a celei de a doua cerințe se acordă 20 de puncte, iar pentru rezolvarea corectă a celei de a treia cerințe se acordă 50 de puncte.
  • În concurs s-au acordat 10 puncte din oficiu. Aici se vor acorda pentru exemplele din enunț.

Exemplul 1:

pal.in

1
3
345 214 64325

pal.out

353 222 64346

Explicație

Șirul palindromurilor de pe lista corectă obținută de Micul Prinț.

Exemplul 2:

pal.in

2
8
2 3 120 4 432 5643461 7 21211

pal.out

3

Explicație

Lista corectă conține palindromurile 2 3 121 4 21212 434 5643465 7 și cel mai lung șir magic este 3 434 5643465.

Exemplul 3:

pal.in

3
8
2 3 5643461 7 120 4 21211 432

pal.out

3 434 5643465

Explicație

Șirul magic 2 121 21212 are aceeași lungime dar se termină într-un număr mai mic.

Cum e corect?

cout < "As la info"; cout << "As la info"; cout >> "As la info";

Felicitări! Poți mai mult?

Avem sute de probleme pentru tine, fiecare cu explicații ușor de înțeles.

Greșit, dar nu-i bai!

Antrenează-te cu sutele de probleme pe care ți le-am pregătit. Îți explicăm fiecare problemă în parte.

Rezolvare

Iată rezolvarea de 100 de puncte pentru problema pal:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define ll long long

int n, i, cerinta, cnt, ans = 0, nr, cf[30];
ll a[50005], z, x, win, v[30];

void load()
{
    int i, j, k, nr, p, aux;
    int ok; ll x;

    for(i=1; i<=n; ++i)
    {
        scanf("%lld", &x); ///fin >> x;
        //assert(0<x && x<=(1e18));

        nr = 0;
        while(x)
        {
            cf[++nr] = x%10;
            x /= 10;
        }

        for(p = 1 ; p<=nr/2; p++) {aux=cf[p]; cf[p]=cf[nr - p + 1]; cf[nr - p + 1]=aux;}
        //reverse(cf+1, cf+nr+1);

        /// compar reverse(prima jumate) cu a doua jumate
        ok = 1;
        for(j=nr/2+2; ok && j<=nr; ++j)
        {
            k = nr - j + 1;
            if(cf[j] < cf[k]) break;
            if(cf[j] > cf[k]) ok = 0;
        }

        if(ok)
            for(j=nr/2+2; j<=nr; ++j) cf[j] = cf[nr-j+1];
        else
        {
            cf[nr/2+1]++;
            j = nr/2+1;
            while(cf[j] == 10) cf[j] = 0, ++cf[--j];
            for(j=nr/2+2; j<=nr; ++j) cf[j] = cf[nr-j+1];
        }

        a[i] = 0;
        for(j=1; j<=nr; ++j) a[i] = a[i] * 10 + cf[j];
    }
}

int cauta(ll x) /// verific daca x apare in vector
{
    int st = 1, dr = n, mid;
    while(st <= dr)
    {
        mid = (st+dr)/2;
        if(a[mid] == x) return 1;
        if(a[mid] < x) st = mid + 1;
            else dr = mid - 1;
    }
    return 0;
}

int compare (const void * a, const void * b)
{
  if( *(long long*)a - *(long long*)b <0) return -1;
  if( *(long long*)a - *(long long*)b >0) return 1;
  return 0;
}


int main()
{
    freopen("pal.in","r",stdin);
    freopen("pal.out","w",stdout);
    scanf("%d %d",&cerinta, &n);

    load();

    if(cerinta == 1)
    {
        for(i=1; i<=n; ++i) printf("%lld ", a[i]); printf("\n");
        return 0;
    }

    qsort(a + 1, n, sizeof(long long), compare);

    for(i=1; i<=n; ++i)
    {
        z = 1;
        x = a[i];
        cnt = 1;

        while(x >= z*10) z *= 10;
        /// z e puterea de 10 corespunzatoare primei cifre

        while(z>1)
        {
            x = (x % z - x % 10) / 10;
            if(cauta(x)) ++cnt;
            z /= 100;
        }

        if(cnt >= ans) ans = cnt, win = a[i];
    }

    if(cerinta == 2)
    {
        printf("%d\n", ans);
        return 0;
    }

    v[nr = 1] = x = win;
    while(x >= z*10) z *= 10;

    while(z>1)
    {
        x = (x % z - x%10) / 10;
        if(cauta(x)) v[++nr] = x;
        z /= 100;
    }

    for(i=nr; i; --i) printf("%lld ", v[i]); printf("\n");
    return 0;
}

Atenție

Enunțurile afișate pe această pagină aparțin exclusiv site-ului PbInfo. Astfel, pentru ștergerea conținutului, puteți să ne contactați la adresa Adresa de email.

Rezolvarea problemei #2438 pal

Pe această pagină găsești rezolvarea de 100 de puncte pentru problema #2438 pal de pe PbInfo.ro. Atenție: nu încurajăm copiatul codului! Totuși, credem cu tărie că analizarea unei soluții corecte este o metodă foarte ușoară de a învăța informatică, astfel că oferim sursele pentru peste 1500 de probleme de pe platforma PbInfo.ro.

Pentru rezolvări PbInfo de la peste 1500 de probleme, vă invităm să intrați pe site-ul nostru!