Hackerrank – Popis problému
Celý popis zadania sa nacháza – Hackerrank.
Riešenie
Máme zadané N. ako ohraničenie maximálneho možného čísla.
Môžeme začať od 3 do N a spočítavať čísla, ktoré sú deliteľné 3 a 5 (použijeme operáciu modulo). Tu nám nemusí vyjsť správny výsledok, pretože niektoré čísla sú započítané 2x. Tie čísla sú deliteľné 15, lebo algoritmus ich započíta aj pri porovnávaní deliteľnosti 3 a 5. Čísla deliteľné 15 musíme z celkového výsledku odpočítať.
Toto riešenie nie je tiež efektívne. Ak by bolo číslo N príliš vysoké a porovnávali by sme postupne deliteľnosť každého čísla, prekročili by sme časový limit na úlohu.
Existuje trik, ako rýchlo spočítať čísla, ktoré sa medzi sebou líšia medzi sebou len vždy o rovnakú hodnotu (v našom prípade o 3, 5 a 15).
Pomôže nám vzťah. Stačí mať najmenšie a najväčšie číslo v postupnosti čísel líšiacich sa o hodnotu d a ich počet n. Ich počet získame, keď vydelíme maximálne číslo v postupnosti číslom d.
Napríklad, ak je N = 20. Najväčšie číslo menšie ako 20, ktoré je deliteľné 3 je 18. Najmenšie je 3. Ich počet dostaneme rovnicou n = 18/3 = 6. Ich súčet bude:
![]()
.
Podobne si vypočítame súčty pre čísla deliteľné 5 a 15.
Rovnica pre vyriešenie úlohy:
![]()
Vytvoril som riešenie v týchto programovacích jazykoch:
Všetky riešenia sú dostupné aj na mojom GitHub profile.
Java
|
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 |
import java.util.Scanner; public class Multiples { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int tests = Integer.parseInt(scanner.nextLine()); for (int i = 0; i < tests; i++) { long number = Long.parseLong(scanner.nextLine()); long result = sumOfMultiples(number); System.out.println(result); } scanner.close(); } // http://en.wikipedia.org/wiki/Arithmetic_progression private static long sumOfMultiples(long number) { long result = 0; if (number > 3) { long min = 3; long count = (number - 1) / 3; long max = number - 1; while (max % 3 != 0) { max--; } long tempResult = count * (min + max) / 2; result += tempResult; } if (number > 5) { long min = 5; long count = (number - 1) / 5; long max = number - 1; while (max % 5 != 0) { max--; } long tempResult = count * (min + max) / 2; result += tempResult; } if (number > 15) { long min = 15; long count = (number - 1) / 15; long max = number - 1; while (max % 15 != 0) { max--; } long tempResult = count * (min + max) / 2; result -= tempResult; } return result; } } |