Skip to content

Commit

Permalink
Merge pull request #244 from pdp-archive/36-luckyagain
Browse files Browse the repository at this point in the history
36 luckyagain
  • Loading branch information
Dim131 authored May 6, 2024
2 parents bb27307 + 54e5294 commit 3c31261
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 0 deletions.
12 changes: 12 additions & 0 deletions _data/contests/36-PDP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,15 @@ allthatjazz:
solution_tags: ["two pointers","sorting","binary search"]
on_judge: true

luckyagain:
full_name: "Τυχεροί αριθμοί"
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: ["map", "bst", "counting", "decimal numbers", "number bases"]
on_judge: false
points: 30
23 changes: 23 additions & 0 deletions _includes/source_code/code/36-PDP/luckyagain/TASK
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
TASK(
name = "luckyagain",
test_count = 18,
files_dir = "testdata/36-PDP/luckyagain/",
input_file = "luckyagain.in",
output_file = "luckyagain.out",
time_limit = 2,
mem_limit = 128,
solutions = [
SOLUTION(
name = "luckyagain_efficient",
source = "luckyagain_efficient.cc",
passes_all,
lang = "c++",
),
SOLUTION(
name = "luckyagain_brute_force",
source = "luckyagain_brute_force.cc",
passes_up_to = 11,
lang = "c++",
),
]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <algorithm>
#include <cstdio>
#include <vector>

typedef long long ll;

bool is_lucky(const std::vector<int>& digitsA, const std::vector<int>& digitsB) {
int total_length = (digitsA.size() + digitsB.size());
if (total_length % 2 == 1) return false; // Αν έχει μονό πλήθος ψηφίων, τότε δεν είναι τυχερός.

int cur_sum[2];
cur_sum[1] = 0; // Το άθροισμα των ψηφίων του πρώτου μισού.
cur_sum[0] = 0; // Το άθροισμα των ψηφίων του δεύτερου μισού.

int midpoint = total_length / 2;
for (int i = 0; i < digitsA.size(); ++i) {
cur_sum[i < midpoint] += digitsA[i];
}
for (int i = 0; i < digitsB.size(); ++i) {
cur_sum[i + digitsA.size() < midpoint] += digitsB[i];
}

return cur_sum[0] == cur_sum[1];
}

int main() {
FILE *fi = fopen("luckyagain.in", "r");
long N;
fscanf(fi, "%ld", &N);

std::vector<std::vector<int>> digits(N);

for (int i = 0; i < N; ++i) {
long temp;
fscanf(fi, "%ld", &temp);

// Βρίσκουμε τα ψηφία ενός αριθμού.
while (temp > 0) {
digits[i].push_back(temp % 10);
temp /= 10;
}
// Δεδομένου του υπόλοιπου κώδικα η ακόλουθη αντιστροφή δεν είναι
// αναγκαία (γιατί;)
// std::reverse(digits[i].begin(), digits[i].end());
}
fclose(fi);

// Μετράμε πόσα από τα δυνατά ζευγάρια φτιάχνουν έναν τυχερό αριθμό.
ll total_count = 0;
for (long i = 0; i < N; ++i) {
for (long j = 0; j < N; ++j) {
if (i == j) continue;
total_count += is_lucky(digits[i], digits[j]);
}
}

FILE *fo = fopen("luckyagain.out", "w");
fprintf(fo, "%lld\n", total_count);
fclose(fo);

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include <cstdio>
#include <vector>

typedef long long ll;

ll counts[10 /* πλήθος ψηφίων */][82 /* άθροισμα ψηφίων */]; // Πλήθος αριθμών

int main() {
FILE *fi = fopen("luckyagain.in", "r");
long N;
fscanf(fi, "%ld", &N);

std::vector<std::vector<int>> digits(N);
std::vector<int> digit_sum(N, 0);

for (int i = 0; i < N; ++i) {
long temp;
fscanf(fi, "%ld", &temp);

// Βρίσκουμε τα ψηφία ενός αριθμού και το άθροισμά τους.
while (temp > 0) {
int cur_digit = temp % 10;
digit_sum[i] += cur_digit;
digits[i].push_back(cur_digit);
temp /= 10;
}

// (Προ)-ϋπολογισμός του πίνακα counts.
++counts[digits[i].size()][digit_sum[i]];
}
fclose(fi);

ll total_count = 0;
// Οι αριθμοί με το ίδιο πλήθος ψηφίων θα μετρηθούν δύο φορές. Επομένως κρατάμε
// το πλήθος αυτών ώστε να το αφαιρέσουμε το μισό από το σύνολο.
ll same_digit_count = 0;
for (int j = 0; j < N; ++j) {
const int sum_of_digits = digit_sum[j];
const int len = digits[j].size();

// Βρίσκουμε το πλήθος των ζευγαριών που έχουν τον j-οστό αριθμό
// σαν πρώτο μέρος και μέσο η θέση (len - i).
int suffix_sum = 0;
for (int i = 0; 2 * i < len; ++i) {
ll cur_count = counts[len - 2 * i][sum_of_digits - 2 * suffix_sum];
total_count += cur_count;
if (i == 0) { // Το μέσο είναι στο τέλος του αριθμού.
same_digit_count += cur_count - 1; // -1, για να μην μετρήσουμε τον εαυτό του.
}
suffix_sum += digits[j][i];
}

// Βρίσκουμε το πλήθος των ζευγαριών που έχουν τον j-οστό αριθμό
// σαν δεύτερο μέρος και μέσο η θέση i.
int prefix_sum = 0;
for (int i = 0; 2 * i < len; ++i) {
ll cur_count = counts[len - 2 * i][sum_of_digits - 2 * prefix_sum];
total_count += cur_count;
if (i == 0) { // Το μέσο είναι στην αρχή του αριθμού.
same_digit_count += cur_count - 1;
}
prefix_sum += digits[j][len - i - 1];
}

// Αφαιρούμε τον εαυτό του απο την μέτρηση.
total_count -= 2;
}
total_count -= same_digit_count / 2;

FILE *fo = fopen("luckyagain.out", "w");
fprintf(fo, "%lld\n", total_count);
fclose(fo);

return 0;
}
1 change: 1 addition & 0 deletions assets/36-c-luckyagain.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 3c31261

Please sign in to comment.