diff --git a/_data/contests/36-PDP.yml b/_data/contests/36-PDP.yml index 4862908b..d5cc1a7b 100755 --- a/_data/contests/36-PDP.yml +++ b/_data/contests/36-PDP.yml @@ -46,3 +46,16 @@ luckyagain: solution_tags: ["map", "bst", "counting", "decimal numbers", "number bases"] on_judge: false points: 30 + +bitsign: + full_name: "Bits με υπογραφή" + stage: "c" + statement_pdf_url: "https://drive.google.com/file/d/1AXuG5L4SzRkTnljViElY8qWqOvNoHOTd/view" + statement_md: true + testcases_url: "" + solution: true + solution_author: "" + codes_in_git: true + solution_tags: ["dp", "exhaustive search", "precomputation"] + on_judge: false + points: 30 diff --git a/_includes/source_code/code/36-PDP/bitsign/TASK b/_includes/source_code/code/36-PDP/bitsign/TASK new file mode 100644 index 00000000..7191fbe5 --- /dev/null +++ b/_includes/source_code/code/36-PDP/bitsign/TASK @@ -0,0 +1,35 @@ +TASK( + name = "bitsign", + test_count = 21, + files_dir = "testdata/36-PDP/bitsign/", + input_file = "bitsign.in", + output_file = "bitsign.out", + time_limit = 1, + mem_limit = 256, + solutions = [ + SOLUTION( + name = "bitsign_dp_n2", + source = "bitsign_dp_n2.cc", + passes_all, + lang = "c++", + ), + SOLUTION( + name = "bitsign_dp_n2_mem", + source = "bitsign_dp_n2_mem.cc", + passes_all, + lang = "c++", + ), + SOLUTION( + name = "bitsign_dp_n3", + source = "bitsign_dp_n3.cc", + passes_all, + lang = "c++", + ), + SOLUTION( + name = "bitsign_brute_force", + source = "bitsign_brute_force.cc", + passes_up_to = 8, + lang = "c++", + ), + ] +) diff --git a/_includes/source_code/code/36-PDP/bitsign/bitsign_brute_force.cc b/_includes/source_code/code/36-PDP/bitsign/bitsign_brute_force.cc new file mode 100644 index 00000000..0218596e --- /dev/null +++ b/_includes/source_code/code/36-PDP/bitsign/bitsign_brute_force.cc @@ -0,0 +1,58 @@ +#include +#include + +const long MOD = 1'000'000'007L; +const int MAXN = 2'000; + +char c[MAXN + 2]; +std::vector s; + +long total; +int N, M; + +/* Δοκιμάζουμε τις δυνατές τιμές για το c[c_idx], δεδομένου ότι έχουμε συμπληρώσει + τις τιμές για τα c[0..c_idx-1], ότι έχουμε φτιάξει τα διαστήματα s[0..s_idx-1] και + ότι το μήκος της τωρινής ακολουθίας από άσους είναι len_of_ones. */ +void solve(int c_idx, int len_of_ones, int s_idx) { + if (c_idx == N + 1) { + // Συμπληρώσαμε όλη την ακολουθία. Ελέγχουμε ότι δεν μας περίσσεψε κάτι. + if (s_idx == s.size() && len_of_ones == 0) total = (total + 1) % MOD; + return; + } + // Δοκιμάζουμε να βάλουμε έναν άσο. Επεκτείνεται η τωρινή ακολουθία κατά ένα. + if (c[c_idx] == '1' || c[c_idx] == '.') solve(c_idx + 1, len_of_ones + 1, s_idx); + // Δοκιμάζουμε να βάλουμε ένα μηδενικό. Αν υπάρχει τωρινή ακολουθία από άσσους + // με μήκος s[s_idx], την ολοκληρώνουμε. + if (c[c_idx] == '0' || c[c_idx] == '.') { + if (s_idx < s.size() && len_of_ones == s[s_idx]) solve(c_idx + 1, 0, s_idx + 1); + else if (len_of_ones == 0) solve(c_idx + 1, 0, s_idx); + } +} + +int main() { + FILE *fi = fopen("bitsign.in", "r"); + FILE *fo = fopen("bitsign.out", "w"); + + int T; + fscanf(fi, "%d\n", &T); + while (T--) { + fscanf(fi, "%d %d\n", &N, &M); + for (int i = 0; i < N; ++i) { + fscanf(fi, "%c", &c[i]); + } + c[N] = '0'; + s.resize(M); + for (int i = 0; i < M; ++i) { + fscanf(fi, "%d", &s[i]); + } + + total = 0; + solve(0, 0, 0); + + fprintf(fo, "%ld\n", total); + } + + fclose(fi); + fclose(fo); + return 0; +} diff --git a/_includes/source_code/code/36-PDP/bitsign/bitsign_dp_n2.cc b/_includes/source_code/code/36-PDP/bitsign/bitsign_dp_n2.cc new file mode 100644 index 00000000..29133a63 --- /dev/null +++ b/_includes/source_code/code/36-PDP/bitsign/bitsign_dp_n2.cc @@ -0,0 +1,57 @@ +#include +#include + +const long MOD = 1'000'000'007L; +const int MAXN = 2'000; + +char c[MAXN + 2]; + +int main() { + FILE *fi = fopen("bitsign.in", "r"); + FILE *fo = fopen("bitsign.out", "w"); + + int T; + fscanf(fi, "%d\n", &T); + while (T--) { + int N, M; + + fscanf(fi, "%d %d\n", &N, &M); + for (int i = 0; i < N; ++i) { + fscanf(fi, "%c", &c[i+1]); + } + c[0] = c[N+1] = '0'; + std::vector s(M); + for (int i = 0; i < M; ++i) { + fscanf(fi, "%d", &s[i]); + } + + // Προϋπολογίζουμε το πρώτο μηδενικό στα δεξιά του κάθε στοιχείου. + std::vector first_zero_to_left(N + 2); + for (int i = N + 1; i >= 0; --i) { + if (c[i] == '0') { + first_zero_to_left[i] = i; + continue; + } + first_zero_to_left[i] = std::min(first_zero_to_left[i+1], i); + while (c[first_zero_to_left[i]] != '0') --first_zero_to_left[i]; + } + + // Ο υπολογισμός με δυναμικό προγραμματισμό. + std::vector> dp(M+1, std::vector(N+2, 0)); + for (int i = 0; i <= N+1 && c[i] != '1'; ++i) dp[0][i] = 1; + + for (int j = 1; j <= M; ++j) { + for (int i = 1; i <= N + 1; ++i) { + if (c[i] == '1') continue; + dp[j][i] = dp[j][i-1]; // Μπορούμε απλά να προσθέσουμε ένα 0. + if (i - first_zero_to_left[i - 1] - 1 >= s[j-1]) // Υπάρχουν αρκετά ‘1' ή ‘.'? + dp[j][i] = (dp[j][i] + dp[j - 1][i - s[j-1] - 1]) % MOD; + } + } + fprintf(fo, "%ld\n", dp[M][N+1]); + } + + fclose(fi); + fclose(fo); + return 0; +} diff --git a/_includes/source_code/code/36-PDP/bitsign/bitsign_dp_n2_mem.cc b/_includes/source_code/code/36-PDP/bitsign/bitsign_dp_n2_mem.cc new file mode 100644 index 00000000..ca1c560a --- /dev/null +++ b/_includes/source_code/code/36-PDP/bitsign/bitsign_dp_n2_mem.cc @@ -0,0 +1,65 @@ +#include +#include + +const long MOD = 1'000'000'007L; +const int MAXN = 2'000; + +char c[MAXN + 2]; + +inline int C(int i) { return i & 1; } + +int main() { + FILE *fi = fopen("bitsign.in", "r"); + FILE *fo = fopen("bitsign.out", "w"); + + int T; + fscanf(fi, "%d\n", &T); + while (T--) { + int N, M; + + fscanf(fi, "%d %d\n", &N, &M); + for (int i = 0; i < N; ++i) { + fscanf(fi, "%c", &c[i+1]); + } + c[0] = c[N+1] = '0'; + std::vector s(M); + for (int i = 0; i < M; ++i) { + fscanf(fi, "%d", &s[i]); + } + + // Προϋπολογίζουμε το πρώτο μηδενικό στα δεξιά του κάθε στοιχείου. + std::vector first_zero_to_left(N + 2); + for (int i = N + 1; i >= 0; --i) { + if (c[i] == '0') { + first_zero_to_left[i] = i; + continue; + } + first_zero_to_left[i] = std::min(first_zero_to_left[i+1], i); + while (c[first_zero_to_left[i]] != '0') --first_zero_to_left[i]; + } + + // Ο υπολογισμός με δυναμικό προγραμματισμό. + std::vector dp[2]; + dp[0].resize(N+2, 0); + dp[1].resize(N+2, 0); + for (int i = 0; i <= N+1 && c[i] != '1'; ++i) dp[0][i] = 1; + + for (int j = 1; j <= M; ++j) { + dp[C(j)][0] = 0; + for (int i = 1; i <= N + 1; ++i) { + if (c[i] == '1') { + dp[C(j)][i] = 0; + } else { + dp[C(j)][i] = dp[C(j)][i-1]; // Μπορούμε απλά να προσθέσουμε ένα 0. + if (i - first_zero_to_left[i - 1] - 1 >= s[j-1]) // Υπάρχουν αρκετά ‘1' ή ‘.'? + dp[C(j)][i] = (dp[C(j)][i] + dp[C(j - 1)][i - s[j-1] - 1]) % MOD; + } + } + } + fprintf(fo, "%ld\n", dp[C(M)][N+1]); + } + + fclose(fi); + fclose(fo); + return 0; +} diff --git a/_includes/source_code/code/36-PDP/bitsign/bitsign_dp_n3.cc b/_includes/source_code/code/36-PDP/bitsign/bitsign_dp_n3.cc new file mode 100644 index 00000000..7c1cc197 --- /dev/null +++ b/_includes/source_code/code/36-PDP/bitsign/bitsign_dp_n3.cc @@ -0,0 +1,49 @@ +#include +#include + +const long MOD = 1'000'000'007L; +const int MAXN = 2'000; + +char c[MAXN + 2]; + +int main() { + FILE *fi = fopen("bitsign.in", "r"); + FILE *fo = fopen("bitsign.out", "w"); + + int T; + fscanf(fi, "%d\n", &T); + while (T--) { + int N, M; + + fscanf(fi, "%d %d\n", &N, &M); + for (int i = 0; i < N; ++i) { + fscanf(fi, "%c", &c[i+1]); + } + c[0] = c[N+1] = '0'; + std::vector s(M); + for (int i = 0; i < M; ++i) { + fscanf(fi, "%d", &s[i]); + } + + // Ο υπολογισμός με δυναμικό προγραμματισμό. + std::vector> dp(M+1, std::vector(N+2, 0)); + for (int i = 0; i <= N+1 && c[i] != '1'; ++i) dp[0][i] = 1; + + for (int j = 1; j <= M; ++j) { + for (int i = 1; i <= N + 1; ++i) { + if (c[i] == '1') continue; + dp[j][i] = dp[j][i-1]; // Μπορούμε απλά να προσθέσουμε ένα 0. + int first_zero_to_left = i - 1; + while (c[first_zero_to_left] != '0') --first_zero_to_left; + if (i - first_zero_to_left - 1 >= s[j-1]) { // Υπάρχουν αρκετά ‘1' ή ‘.'? + dp[j][i] = (dp[j][i] + dp[j - 1][i - s[j-1] - 1]) % MOD; + } + } + } + fprintf(fo, "%ld\n", dp[M][N+1]); + } + + fclose(fi); + fclose(fo); + return 0; +} diff --git a/assets/36-c-bitsign.svg b/assets/36-c-bitsign.svg new file mode 100644 index 00000000..7563a0ee --- /dev/null +++ b/assets/36-c-bitsign.svg @@ -0,0 +1 @@ +s[𝑗]στοιχεία10.𝑖1.0Οποιοσδήποτε τρόπος νασυμπληρώσουμεαυτάταστοιχείαμετα μήκηs[1..𝑗1]0𝑖Οποιοσδήποτε τρόπος νασυμπληρώσουμεαυτά τα στοιχεία μετα μήκηs[1..𝑗]𝑑𝑝𝑗[𝑖1]τρόποι𝑑𝑝𝑗1[𝑖𝑠𝑗1]τρόποι \ No newline at end of file diff --git a/contests/_36-PDP/c-bitsign-solution.md b/contests/_36-PDP/c-bitsign-solution.md new file mode 100644 index 00000000..5c26efa4 --- /dev/null +++ b/contests/_36-PDP/c-bitsign-solution.md @@ -0,0 +1,60 @@ +--- +layout: solution +codename: bitsign +--- + +## Επεξήγηση εκφώνησης + +Μας δίνεται μία ακολουθία $$\texttt{c}$$ με χαρακτήρες '0', '1' και '.', και μία ακολουθία $$\texttt{s}$$ με ακέραιους αριθμούς. Μας ζητείται να βρούμε με πόσους τρόπους μπορούμε να αντικαταστήσουμε τους χαρακτήρες '.' με ψηφία '0' ή '1' στην $$\texttt{c}$$ ώστε η ακολουθία του πλήθους των διαδοχικών '1' να είναι η $$\texttt{s}$$. + +Για παράδειγμα, για τις ακολουθίες $$\texttt{c} = \texttt{0..00..000.110}$$ και $$\texttt{s} = \texttt{1 1 3}$$, δύο πιθανές απαντήσεις είναι οι εξής: + +$$\texttt{0\underline{\textcolor{red}{1}0}00\underline{\textcolor{red}{1}0}000\underline{\textcolor{red}{1}}\textcolor{red}{11}0} \quad \text{και} \quad \texttt{0\underline{\textcolor{red}{1}0}00\underline{0\textcolor{red}{1}}000\underline{\textcolor{red}{1}}\textcolor{red}{11}0}.$$ + +## Εξαντλητική λύση + +Μία λύση είναι να δοκιμάσουμε όλες τις δυνατές τιμές $$0$$ και $$1$$ για κάθε θέση της $$\texttt{c}$$ που έχει '.'. Στην χειρότερη περίπτωση χρειάζεται να ελέγξουμε $$\Theta(2^N)$$ δυνατές ακολουθίες, επομένως ο αλγόριθμος χρειάζεται $$\mathcal{O}(2^N)$$ χρόνο. + +Μπορούμε να υλοποιήσουμε αυτές τις δοκιμές αναδρομικά ως εξής: + +{% include code.md solution_name='bitsign_brute_force.cc' start=13 end=30 %} + +και η αρχική κλήση είναι η εξής: +{% include code.md solution_name='bitsign_brute_force.cc' start=49 end=50 %} + +Μπορείτε να βρείτε ολόκληρο των κώδικα [εδώ]({% include link_to_source.md solution_name='bitsign_brute_force.cc' %}). + +## Λύση με δυναμικό προγραμματισμό σε $$\mathcal{O}(N^2 M)$$ χρόνο + +Ο παραπάνω αναδρομικός αλγόριθμος μπορεί να λύσει πολλές φορές το ίδιο υποπρόβλημα. Θα χρησιμοποιήσουμε [δυναμικό προγραμματισμό](https://kallinikos.github.io/Dynamic-Programming), μία αποδοτική τεχνική που σπάει το πρόβλημα σε διαδοχικά μικρότερα υποβροβλήματα και για κάθε ένα από αυτά υπολογίζει την λύση μία φορά. + +Ορίζουμε ως `dp[j][i]` το πλήθος των δυνατών τρόπων να αντισταταστήσουμε τα '.' στις θέσεις `c[1..i]` ώστε να έχουμε συμπληρώσει ακολουθίες διαδοχικών άσων με μήκη `s[1..j]`. Για χάριν ευκολίας, λέμε ότι *συμπληρώνεται* μία ακολουθία από διαδοχικούς άσους αφού προσθέσουμε το μηδέν μετά τον τελευταίο άσο. Επιπλέον, προσθέτουμε ένα μηδενικό στο τέλος του `c` (το οποίο δεν αλλάζει την απάντηση), ώστε να ολοκληρωθεί η τελευταία ακολουθία από άσους. Άρα σε κάθε θέση `c[i] = ‘1’` έχουμε εξ ορισμού ότι `dp[j][i] = 0`. + +Αν το στοιχείο `c[i] = ‘0'` ή `c[i] = ‘.'`, έχουμε δύο τρόπους να επεκτείνουμε τις υπάρχουσες ακολουθίες: + 1. Επεκτείνουμε όλες τις λύσεις στο `dp[j][i-1]` προσθέτοντας ένα μηδενικό στο τέλος τους. + 2. Αν μπορούμε να βάλουμε `s[j]` άσους στις θέσεις `c[(i - s[j] - 1)..(i-1)]`, δηλαδή αυτές οι θέσεις έχουν μόνο χαρακτήρες '1' ή '.', τότε έχουμε `dp[j - 1][i - s[j] - 1]` επιπλέον τρόπους. + +
+ +
+ +Ο παρακάτω κώδικας συμπληρώνει τον πίνακα `dp` και η απάντηση βρίσκεται στην θέση `dp[M][N+1]`. +{% include code.md solution_name='bitsign_dp_n3.cc' start=30 end=42 %} + +Ο έλεγχος για τα στοιχεία `c[(i-s[j]-1)..(i-1)]` χρειάζεται $$\mathcal{O}(N)$$ χρόνο, άρα αφού υπάρχουν $$\mathcal{O}(NM)$$ θέσεις στον πίνακα `dp`, συνολικά ο αλγόριθμος χρειάζεται $$\mathcal{O}(N^2M)$$ χρόνο και $$\mathcal{O}(NM)$$ μνήμη. + +Μπορείτε να βρείτε ολόκληρο των κώδικα [εδώ]({% include link_to_source.md solution_name='bitsign_brute_force.cc' %}). + +## Λύση με δυναμικό προγραμματισμό (σε $$\mathcal{O}(N M)$$ χρόνο) + +Μπορούμε να επιταγχύνουμε την προηγούμενη λύση προϋπολογίζοντας τις τιμές `first_zero_to_left` για κάθε θέση `i` σε χρόνο $$\mathcal{O}(N)$$ (ακόμα και $$\mathcal{O}(N^2)$$ θα ήταν αρκετό), ως εξής: + +{% include code.md solution_name='bitsign_dp_n2.cc' start=28 end=37 %} + +Ο κυρίως κώδικας αλλάζει ως εξής: + +{% include code.md solution_name='bitsign_dp_n2.cc' start=41 end=50 %} + +Έτσι χρειάζομαστε $$\mathcal{O}(1)$$ χρόνο για τον υπολογισμό της κάθε τιμής του πίνακα $$\texttt{dp}$$, συνεπώς ο αλγόριθμος τρέχει σε $$\mathcal{O}(NM)$$ χρόνο. Μπορείτε να βρείτε ολόκληρο τον κώδικα [εδώ]({% include link_to_source.md solution_name='bitsign_dp_n2.cc' %}). + +Επιπλέον αν παρατηρήσετε ότι για τον υπολογισμό των τιμών $$\texttt{dp}[j][\cdot]$$ χρησιμοποιούμε μόνο τις τιμές $$\texttt{dp}[j-1][\cdot]$$, μπορούμε να κρατάμε μόνο δύο γραμμές στον πίνακα `dp`, μειώνοντας τον συνολικό χώρο σε $$\mathcal{O}(N)$$. Δείτε [εδώ]({% include link_to_source.md solution_name='bitsign_dp_n2_mem.cc' %}). diff --git a/contests/_36-PDP/c-bitsign-statement.md b/contests/_36-PDP/c-bitsign-statement.md new file mode 100644 index 00000000..ae0c867a --- /dev/null +++ b/contests/_36-PDP/c-bitsign-statement.md @@ -0,0 +1,93 @@ +--- +layout: statement +codename: bitsign +--- + +Έστω μια ακολουθία αποτελούμενη από δυαδικά ψηφία (bits). Για τις +ανάγκες αυτής της άσκησης, θα υπολογίζουμε την **υπογραφή** αυτής της +ακολουθίας μετρώντας το πλήθος των διαδοχικών ψηφίων "1" (άσων) που +εμφανίζονται σε αυτήν. Για παράδειγμα, έστω η ακολουθία: + +$$\texttt{00{\color{red}111}0{\textcolor{red}{11}}000{\color{red}1111}0{\color{red}1}}$$ + +Στην ακολουθία αυτή εμφανίζονται πρώτα τρεις ($$3$$) διαδοχικοί άσοι, μετά +άλλοι δύο ($$2$$), μετά άλλοι τέσσερις ($$4$$) και στο τέλος άλλος ένας ($$1$$). Η +υπογραφή λοιπόν αυτής της ακολουθίας αποτελείται από τέσσερις +αριθμούς: $$3$$, $$2$$, $$4$$, $$1$$. Δηλαδή, για να βρούμε την υπογραφή μιας +ακολουθίας, προσπερνάμε τα μηδενικά (λειτουργούν μόνο ως διαχωριστές) +και μετράμε το πλήθος των συνεχόμενων άσων που συναντάμε. + +Προσέξτε ότι ακριβώς την ίδια υπογραφή έχει και η ακολουθία: + +$$\texttt{\textcolor{red}{111}0000\textcolor{red}{11}0\textcolor{red}{1111}00000\textcolor{red}{1}0000}$$ + +Σας δίνεται μία ακολουθία αποτελούμενη από $$N$$ δυαδικά ψηφία, κάποια +από τα οποία είναι όμως σβησμένα: στη θέση τους υπάρχει το σύμβολο της +τελείας. Για παράδειγμα: + +$$\texttt{00.\textcolor{red}{11}.\textcolor{red}{11}0....\textcolor{red}{1}..\textcolor{red}{1}}$$ + +Σας δίνεται επίσης μία επιθυμητή υπογραφή, π.χ. $$3$$, $$2$$, $$4$$, $$1$$. +Με πόσους διαφορετικούς τρόπους μπορείτε να συμπληρώσετε τις τελείες +με δυαδικά ψηφία, έτσι ώστε η ακολουθία δυαδικών ψηφίων που θα +προκύψει να έχει τη δοθείσα υπογραφή; + +## Πρόβλημα + +Να αναπτύξετε ένα πρόγραμμα σε μια από τις γλώσσες Pascal, C, C++, +Java το οποίο θα διαβάζει $$T$$ ερωτήματα της παραπάνω μορφής. Για κάθε +ερώτημα θα δίνεται μια ακολουθία δυαδικών ψηφίων, από τα οποία κάποια +θα είναι σβησμένα, και μια επιθυμητή υπογραφή. Για κάθε ερώτημα, το +πρόγραμμά σας πρέπει να εκτυπώνει το πλήθος των τρόπων με τους +οποίους μπορούν να συμπληρωθούν τα σβησμένα ψηφία, έτσι ώστε η +ακολουθία που θα προκύψει να έχει την επιθυμητή υπογραφή. + +## Αρχεία εισόδου: +Το αρχείο εισόδου με όνομα **bitsign.in** είναι αρχείο κειμένου με την εξής +δομή. Η πρώτη γραμμή περιέχει έναν ακέραιο αριθμό $$T$$, το πλήθος των +ερωτημάτων που θα ακολουθήσουν. Ακολουθούν τα $$T$$ ερωτήματα, που το +καθένα περιγράφεται από τρεις γραμμές της εισόδου. Η πρώτη από αυτές +θα περιέχει δύο ακέραιους αριθμούς $$N$$ και $$M$$, χωρισμένους μεταξύ τους με +ένα κενό διάστημα: το πλήθος των ψηφίων της ακολουθίας και το πλήθος +των αριθμών της υπογραφής. Η δεύτερη θα περιέχει μία συμβολοσειρά +αποτελούμενη από $$N$$ χαρακτήρες που καθένας μπορεί να είναι "0", "1" ή "." +(τελεία). Η τρίτη θα περιέχει $$M$$ θετικούς ακέραιους αριθμούς, χωρισμένους +ανά δύο με ένα κενό διάστημα: την επιθυμητή υπογραφή. + +## Αρχεία εξόδου: +Το αρχείο εξόδου με όνομα **bitsign.out** είναι αρχείο κειμένου με την εξής +δομή. Θα πρέπει να περιέχει $$T$$ γραμμές: μία γραμμή για κάθε ερώτημα, +κατά σειρά. Κάθε γραμμή θα πρέπει να περιέχει έναν ακέραιο, την +απάντηση στο αντίστοιχο ερώτημα. Επειδή οι απαντήσεις μπορεί γενικά να +είναι πολύ μεγάλοι αριθμοί, εκτυπώστε το υπόλοιπο (modulo) της διαίρεσής +τους με τον αριθμό $$1.000.000.007$$. + +## Παράδειγμα αρχείου εισόδου – εξόδου + +| **bitsign.in** | **bitsign.out** | +| :--- | :--- | +| 5
7 3
...0111
1 1 3
14 3
0..00..000.110
1 1 3
15 4
.1.1.1.1.1.1.1.
1 3 1 6
13 3
.0..0.0001000
4 1 1
12 3
.111........
3 2 1 | 1
4
1
0
10 | + + +*Εξήγηση:* Έχουμε $$T=5$$ ερωτήματα. + - Στο πρώτο ερώτημα, μπορούμε να συμπληρώσουμε την ακολουθία μόνο με έναν τρόπο, έτσι ώστε να προκύψει η επιθυμητή υπογραφή (υπογραμμισμένα τα σβησμένα ψηφία που συμπληρώθηκαν): $$\texttt{\underline{\textcolor{red}{1}0\textcolor{red}{1}}0\textcolor{red}{111}}$$ + - Στο δεύτερο όμως ερώτημα, για την ίδια υπογραφή, μπορούμε να συμπληρώσουμε την ακολουθία με τέσσερις διαφορετικούς τρόπους: $$\texttt{0\underline{\textcolor{red}{1}0}00\underline{\textcolor{red}{1}0}000\underline{\textcolor{red}{1}}\textcolor{red}{11}0}$$, $$\texttt{0\underline{\textcolor{red}{1}0}00\underline{0\textcolor{red}{1}}000\underline{\textcolor{red}{1}}\textcolor{red}{11}0}$$, $$\texttt{0\underline{0\textcolor{red}{1}}00\underline{\textcolor{red}{1}0}000\underline{\textcolor{red}{1}}\textcolor{red}{11}0}$$ και $$\texttt{0\underline{0\textcolor{red}{1}}00\underline{0\textcolor{red}{1}}000\underline{\textcolor{red}{1}}\textcolor{red}{111}0}$$ + - Στο τρίτο ερώτημα, υπάρχει πάλι μόνο ένας τρόπος να συμπληρώσουμε την ακολουθία για να προκύψει η επιθυμητή υπογραφή: $$\texttt{\underline{0}\textcolor{red}{1}\underline{0}\textcolor{red}{1}\underline{\textcolor{red}{1}}\textcolor{red}{1}\underline{0}\textcolor{red}{1}\underline{0}\textcolor{red}{1}\underline{\textcolor{red}{1}}\textcolor{red}{1}\underline{\textcolor{red}{1}}\textcolor{red}{1}\underline{\textcolor{red}{1}}}$$ + - Στο τέταρτο ερώτημα, δεν υπάρχει κανένας τρόπος με τον οποίο να μπορεί να προκύψει η επιθυμητή υπογραφή, καθώς δεν μπορούν να προκύψουν τέσσερις συνεχόμενοι άσοι. + - Στο τελευταίο ερώτημα, η σωστή απάντηση είναι $$10$$. + +## Περιορισμοί: + - $$1 \leq T \leq 10$$, + - $$1 \leq N \leq 2.000$$ και $$1 \leq M \leq 1.000$$, + - Το άθροισμα των μηκών των ακολουθιών όλων των ερωτημάτων δε θα υπερβαίνει το $$3.000$$. + +## Subtasks + - Για περιπτώσεις ελέγχου συνολικής αξίας 20%, θα είναι $$N \leq 15$$. + - Για περιπτώσεις ελέγχου συνολικής αξίας 30%, το πλήθος των σβησμένων ψηφίων κάθε ακολουθίας δε θα υπερβαίνει το $$15$$. + - Για περιπτώσεις ελέγχου συνολικής αξίας 50%, θα είναι $$N \leq 100$$. + +**Προσοχή!** Φροντίστε να διαβάζετε την είσοδο και να εκτυπώνετε την έξοδο αποδοτικά, ειδικά αν προγραμματίζετε σε C++ ή Java. + +**Μορφοποίηση:** Στην έξοδο, όλες οι γραμμές τερματίζουν με ένα χαρακτήρα newline.
+**Μέγιστος χρόνος εκτέλεσης:** 1 sec.
+**Μέγιστη διαθέσιμη μνήμη:** 256 MB. diff --git a/css/main.scss b/css/main.scss index 24096212..7fef7e74 100644 --- a/css/main.scss +++ b/css/main.scss @@ -7,6 +7,11 @@ body { font-family: "Segoe UI", Helvetica; } +/* Font size of math formulas. */ +.katex { font-size: 1.1em !important; } +/* Font size of inline code. (Should match size of math formulas. */ +.language-plaintext { font-size: 1.1em; } + code { font-family: 'KaTeX_Typewriter'; }