Rezolvare completă PbInfo #1611 Palindrom2

Un număr se numește palindrom dacă prima lui cifră este egală cu ultima, a doua cu penultima și așa mai departe. De exemplu numerele 1221, 505 și 7 sunt palindromuri, în vreme ce 500, 1410 și 2424 nu sunt palindromuri.

Similar, un număr se numește aproape palindrom dacă are aceleași perechi de cifre identice ca un palindrom, mai puțin o pereche în care cifrele diferă. De exemplu numerele 500, 1411, 2444, 1220, 53625, 14 și 4014 sunt numere aproape palindromuri, în vreme ce 1221, 1410, 6, 505, 22 și 512125 nu sunt numere aproape palindromuri deoarece fie sunt palindromuri, fie au prea multe perechi de cifre diferite.

Mai definim palindromul asociat al unui număr x ca fiind cel mai mic număr palindrom p strict mai mare decât x (p>x). De exemplu palindromul asociat al lui 5442 este 5445, palindromul asociat al lui 2445 este 2552, al lui 545 este 555, al lui 39995 este 40004, al lui 500 este 505, iar al lui 512125 este 512215.

Cerințe

Scrieţi un program care citind un număr natural nenul n și apoi un șir de n numere naturale determină:

1. câte dintre cele n numere sunt palindrom
2. câte dintre cele n numere sunt aproape palindrom
3. palindromurile asociate pentru cele n numere citite.

Date de intrare

Fișierul de intrare palindrom2.in conține pe prima linie un număr C. Pentru toate testele, C poate lua numai valorile 1, 2 sau 3. Pe a doua linie se află numărul n, iar pe a treia linie cele n numere naturale despărțite prin câte un spațiu.

Date de ieșire

Fișierul de ieșire palindrom2.out:

  • dacă C=1, va conține un singur număr natural reprezentând numărul de numere palindrom din șir
  • dacă C=2, va conține numărul de numere din șir care sunt aproape palindrom
  • dacă C=3, va conține numerele palindrom asociate celor n numere din șir, separate prin câte un spațiu

Restricții și precizări

  • 1 ≤ n ≤ 10 000
  • 1 ≤ numerele din șir ≤ 2 000 000 000
  • Pentru rezolvarea corectă a primei cerinţe se acordă 20 de puncte, pentru rezolvarea corectă a celei de a doua cerințe se acordă 30 de puncte, iar pentru rezolvarea corectă a celei de a treia cerințe se acordă 50 de puncte.

Exemplul 1

palindrom2.in

1
7
1221 500 53635 505 7 4004 1410

palindrom2.out

5

Explicație

Explicație: Cele 5 numere palindrom sunt 1221, 53635, 505, 7 și 4004. (C fiind 1, se rezolvă doar prima cerință)

Exemplul 2

palindrom2.in

2
4
5442 2445 545 39995

palindrom2.out

3

Explicație

Explicație: Cele 3 numere aproape palindrom sunt 5442, 2445 și 39995. (C fiind 2, se rezolvă doar a doua cerință)

Exemplul 3

palindrom2.in

3
11
6 1411 2444 1221 505 1220 53625 14 4014 1410 22

palindrom2.out

7 1441 2552 1331 515 1221 53635 22 4114 1441 33

Explicație

Explicație: Palindromul asociat lui 6 este 7, al lui 1411 este 1441, al lui 2444 este 2552 etc. (C fiind 3, se rezolvă doar a treia cerință)

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 Palindrom2:

/*
  Cristian Francu 2016-02-01
  Solutie optima la punctul (3)
  - Testul de palindrom/aproape palindrom se face prin compararea cifrelor
    simetrice, ceea ce nu produce depasiri in cazuri gen 1 999 999 999
  - Palindromul asociat se genereaza in O(log x) (numarul de cifre ale lui x)
*/
#include <stdio.h>

int main() {
  FILE *fin, *fout;
  int c, n, i, x, cx, y, z, ndif, npali, napr, p10s, p10d;

  fin = fopen( "palindrom2.in", "r" );
  fout = fopen( "palindrom2.out", "w" );
  fscanf( fin, "%d%d", &c, &n );
  if ( c < 3 ) { // primele doua subpuncte se rezolva similar
    npali = napr = 0;
    for ( i = 0; i < n; i++ ) { // citim cele n numere
      fscanf( fin, "%d", &x );
      // punctele 1 si 2, este palindrom sau aproape palindrom?
      // calculam cea mai mare putere a lui 10 care incape in x
      p10s = 1000000000; // ea nu poate fi mai mare ca 1 miliard
      while ( p10s > x )
        p10s /= 10;
      // calculam numarul de diferente intre cifrele lui x si y
      ndif = 0;
      cx = x;
      while ( cx > 0 ) {
        if ( cx / p10s != cx % 10 ) // comparam prima si ultima cifra
          ndif++;
        cx = cx % p10s / 10; // eliminam prima si ultima cifra din cx
        p10s /= 100; // ajustam puterea lui 10
      }
      // in functie de ndif verificam daca e palindrom sau aproape palindrom
      if ( ndif == 0 )
        npali++;
      else if ( ndif == 1 )
        napr++;
    }
    fprintf( fout, "%d\n", c == 1 ? npali : napr );
  } else { // punctul 3, palindromurile asociate (cel mai mic p > x) 
    for ( i = 0; i < n; i++ ) { // citim cele n numere
      fscanf( fin, "%d", &x );

      x++;
      p10d = 1;
      p10s = 1000000000; // cea mai mare putere plauzibila a lui 10
      while ( p10s > x )
        p10s /= 10;
      // calculam rasturnatul primei jumatati a lui x in y
      y = 0;
      while ( p10s > p10d ) {
        y = y + x / p10s % 10 * p10d; // prima cifra a lui cx la inceputul lui y
        p10s /= 10;
        p10d *= 10;
      }
      if ( y >= x % p10d ) // rasturnind prima jumate peste ultima obtinem
        // un palindrom mai mare ca cel original?
        x = x - x % p10d + y; // atunci acesta este palindromul cautat
      else { // trebuie sa adunam 1 la prima jumate si sa o rasturnam
        // adaugind-o la coada (y este acum inutil)
        x = y = 1 + x / p10d; // prima jumate, inclusiv centrul la nr cif impar
        if ( p10s == p10d ) // daca nr cf e impar taiem ultima cifra a lui y
          y /= 10;
        // rasturnam y in z
        z = 0;
        while ( y > 0 ) {
          z = z * 10 + y % 10;
          y /= 10;
        }
        x = x * p10d + z; // compunem prima jumatate cu prima jumatate intoarsa
      }

      fprintf( fout, "%d ", x );
    }
    fprintf( fout, "\n" );
  }
  fclose( fin );
  fclose( fout );

  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 #1611 Palindrom2

Pe această pagină găsești rezolvarea de 100 de puncte pentru problema #1611 Palindrom2 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!