Potyczki algorytmiczne runda próbna

0

Witajcie, może ktoś z was brał udział w tegorocznej rudzie próbnej z przed paru dni i macie jakiś pomysł na wzorcówkę do zadania z rundy próbnej bo zdobyłem z niej 3 punkty i zachodzę w głowę jak powinno wyglądać prawidłowe rozwiązanie

0

Nie brałem udziału i teraz nie ma możliwości sprawdzenia, ale przyszedł mi do głowy taki pomysł:
Zakres [1, 1018] jest zbyt duży, żeby sprawdzić dla każdej liczby czy spełnia podane warunki (pewnie dlatego dostałeś 3 punkty, bo dla większych testów program po prostu za długo liczy). Ale można zauważyć pewne prawidłowości:

  1. Jeżeli k jest mały, to liczby, które spełniają warunek też są małe. Jeśli powiedzmy k < 100 to od razu widać, że nie ma sensu rozpatrywać liczb większych niż np. 106, bo maksymalna suma cyfr liczby 6-cyfrowej to 6 * 9 * 9, więc k * 6 * 9 * 9 nigdy nie będzie większe niż 106
  2. Dla każdego k można w takim razie wyznaczyć w miarę sensowny zakres możliwych trafień. Trzeba sprawdzić czy liczby 1-cyfrowe mogą, 2-cyfrowe mogą, 3-cyfrowe mogą itd. Strzelam, że taki zakres nie obejmuje więcej niż 4 rzędów wielkości.
  3. Problem pozostaje wtedy, gdy te rzędy wielkości są duże, np. dla pewnego k możliwe liczby są 15-cyfrowe, 16-cyfrowe, 17-cyfrowe, 18-cyfrowe w zakresie [A, B]. Sprawdzenie wszystkich takich liczb nadal trwa za długo. Ale wtedy można zauważyć, że jeżeli takie są zakresy, to k też musi być dużą liczbą. Strzelam, że k będzie jakieś 2 rzędy wielkości mniejsze niż A, czyli to jakaś 13-cyfrowa liczba.
  4. Wiedząc o tym, możemy spokojnie sprawdzić tylko liczby podzielne przez k w zakresie [A, B]. Taka pętla zamiast 1018 iteracji będzie miała jakieś 106 iteracji, bo zwiększamy licznik nie o 1 tylko k.
1

Ja też nie brałem udziału, ale coś takiego działa :

#include <iostream>
using namespace std;

int main() {
    long long k,a,b;
    cin >> k >> a >> b;
    int count = 0;
    for(int i=1;i<=1539;i++) {
        long long n = k * i;
        long tmp = n;
        int result = 0;
        while(tmp > 0) {
            int last = tmp % 10;
            result += (last*last);
            tmp /= 10;
        }
        if(result == i && n >= a && n <= b) {
            count++;
        }
    }
    cout << count << "\n";
    return 0;
}
 

Ideaa jest taka, że największa suma kwadratów, czyli f(n) będzie wtedy gdy będzie siedemnascie 9 czyli ~ 1377 . W powyzszym rozwiazaniu przyjelem troche wiecej. Iterujemy sie po wszystkich mozliwych sumach. Obliczamy dla danego k jakie powinno byc n. Dla tak wyliczonego n sprawdzamy czy suma kwadratow cyfr sie zgadza. Jesli tak to inkrementujemy licznik o 1

0
using System;
using System.Linq;

namespace PotyczkiAlgoryttmiczneROW
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] liczby=(Console.ReadLine().Split(' ')).Select(int.Parse).ToArray();
            int rozwiazanie=0;
            for (int i=liczby[1]; i <= liczby[2]; i++ )
            {
                int wynik=0;
                string liczba=i.ToString();
                for (int a = 0; a != liczba.Length; a++)
                    wynik += int.Parse(liczba[a].ToString()) * int.Parse(liczba[a].ToString());
                if (liczby[0] * wynik == i)
                    rozwiazanie++;
            }
            Console.WriteLine(rozwiazanie);
            Console.ReadKey();
        }
    }
}

Też nie biorę udziału, ale z nudy zrobiłem.
Mógłby ktoś wyrazić opinię nt. powyższego kodu?

1 użytkowników online, w tym zalogowanych: 0, gości: 1