Καλύτερη λύση στο happy (27ος camp seniors) #233
doublemidi
started this conversation in
General
Replies: 1 comment 1 reply
-
Πολύ ωραία λύση και καλογραμμένη εξήγηση! Υ. Γ. Υπάρχει ένα μικρό μπέρδεμα με το x και το j στο "Θέτουμε p(i, x) .." Υ. Γ. 2. Μετέφερα το issue στο discussion (που πριν δεν ήταν ανοιχτό). |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Βρήκα εναλλακτική και καλύτερη λύση για το πρόβλημα που πέρνει$Ο(1)$ ανά ερώτημα, αντί για το $Ο(sqrt(maxA))$ που έχει στον κώδικα του github ($maxA$ είναι η μέγιστη τιμή για $Α, Β$ στα ερωτήματα). Συγγνώμη αν είναι λάθος μέρος να το ανεβάσω αυτό (στα issues), δεν είμαι καθόλου εξικιωμένος με το github. Στο υπόλοιπο του post εξηγώ την λύση, μαζί με κώδικα.
Αρχικά, όταν μας δίνεται το ερώτημα$A$ $B$ , μπορούμε να υπολογίσουμε το πλήθος των χαρούμενων στο $[1, Α-1]$ και στο $[1, Β]$ και να τους αφερέσουμε.$[1, Α]$ .
χ.β.γ., κοιτάμε το
Θέτουμε$S(x)$ , το άθροισμα των τετραγώνων των ψηφίων του $x$ .$f(x)$ , το "happiness" του $x$ . Αν ο $x$ , $f(x)=1$ , αλλιώς $f(x)=0$
Θέτουμε
Παρατήρηση 1:$S(x) \leq 9*9*9=729$ για $x\leq maxA$ και $S(x) \leq 6*9*9=486$ για $x<=1'000'000$ .$f(x)$ , για $x \leq 729$ . Δεν θα εξηγήσω πώς, γιατί αυτό γίνεται και στον κώδικα του pdp.
Κάνουμε precompute την
Τώρα, χωρίζουμε το εύρος$[1, 10^9]$ σε $1'000'000$ χιλιάδες.$S(x)$ , για $x \leq 1'000'000$ . Αυτό μπορεί να γίνει σε $Ο(n)$ (αντί για $O(nlogn)$ ) (εδώ $n=1'000'000$ ), με dp, όπου $dp()$ = $S()$ , ως εξής:
$S(0)=0$
$S(x) = (x\%10)^2 + S(x/10)$ , δηλαδή πέρνουμε κάποιο ψηφίο του $x$ (το τελευταίο σε αυτήν την περίπτωση), και αθροίζουμε το τετράγωνο του ψηφίου αυτού μαζί με την $S$ του $x$ , χωρίς το ψηφίο αυτό.
Κάνουμε precompute την
Παρατήρηση 2:$ f(x) = f(S(x))$ $f(x)$ , για $x \leq 1'000'000$ σε $Ο(1)$ .
Έτσι, μπορούμε να υπολογίσουμε την
Θέτουμε$g(i) = \sum\limits_{n=0}^{999} f(i*1000 + n)$ , δηλαδή το άθροισμα της $g()$ για τιμές στην $i$ -οστή χιλιάδα.$g(i)$ για κάθε $0 \leq i \leq 999'999$ .$S(i)=S(j) => g(i)=g(j)$ .$S(i)=S(j) => f(1000*i + x) = f(1000*j + x) = f(S(i)+S(x))$ , για x<1000, αφού τα ψηφία των $i/j$ και του $x$ είναι "ανεξάρτητα".
Θέλουμε να κάνουμε precompute το
Παρατήρηση 3:
Αυτό είναι προφανές, αφού
Αρκεί λοιπόν να υπολογήσουμε μία τιμή της$g()$ για κάθε πιθανή τιμή της $S()$ .$h(S(i)) = g(i)$ , έτσι ώστε $S(i)=x$ . Η $h()$ στον κώδικα λέγεται "thousands_to"$h(x)$ , για $x\leq486$ brute force$g(i), i<1'000'000$ , σε $Ο(1)$ για κάθε $i$ με την βοήθεια της $h()$ .
Θέτουμε λοιπόν
Υπολογίζουμε την
Έπειτα υπολογίζουμε την
Για κάθε ερώτημα, θέλουμε να υπολογίσουμε ένα prefix sum της$g()$ , και απο την τελευταία χιλιάδα, κάποιο κομμάτι της. Για παράδειγμα, αν στο ερώτημα έχουμε $Α=3422$ , η απάντηση είναι $g(0) + g(1) + g(2) +$ τις υπόλοιπες $422$ τιμές που θα δούμε σε λίγο πως θα τις υπολογίζουμε.$g()$ , μπορούμε πολύ απλάνα αποθηκεύσουμε τα prefix sums της $g()$ . Στον κώδικα, ο prefix sum πίνακας στον κώδικα λέγεται "thousands".
Για το prefix sum της
Θέτουμε$p(i, x) = \sum\limits_{n=0}^{999} f(i*1'000'000 + n)$ $S(i)=S(j) => p(i, x) = p(j, x)$ .$486$ τιμές της $p(i, x)$ και, ομοίως,$q(S(i), x) = p(i, x)$ .$q()$ για $i \leq 468$ brute force και ομοίως, αποθηκεύουμε το prefix sum (ως προς $x$ ) της $q$ .$p(i, x)$ , είναι ίσο με το prefix sum της $q(S(i), x)$ .
Παρόμοια με την παρατήρηση 3, έχουμε
Oμοίως, αρκεί να υπολογίσουμε μόνο
θέτουμε
Υπολογίζουμε την
O prefix sum πίνακας στον κώδικα λέγεται "therest".
Για κάθε ερώτημα λοιπόν, όταν θέλουμε να υπολογίσουμε το prefix sum της
Τέλος, παραλείποντας κάποιες λεπτομέριες, η απάντηση του ερωτήματος είναι$0$ ή $1$ -indexed, και κάποια edge cases, όταν $A=maxA$ ή όταν $Α<1'000$
thousands[x/1000] + therest[S[x/1000]][x%1000]
.Οι λεπτομέριες αυτές είναι το αν οι πίνακες μας είναι
Σημείωση: Πολλές φορές μπορεί να μην υπολογίζουμε την$f(0)$ , αλλά $f(0)=0$ , άρα δεν μας νοιάζει αν το υπολογίζουμε.
Κώδικας:
Beta Was this translation helpful? Give feedback.
All reactions