Editorial for Name Tag Tally
Submitting an official solution before solving the problem yourself is a bannable offence.
Author:
There's quite a bit to process with this question, so let's break it down.
You play a game where you select name tags from a bag, with each name tag containing a name consisting of three lowercase English letters. The name on the name tag will be used to calculate your score for that a round.
There are rounds to play, where in each round, you are given three variables
,
, and
, which are also used to calculate the final score.
Based on the rules that are given to you concerning these variables, you want to calculate what your score would be on average, when considering all possible permutations of of the characters in the name.
The Naive Approach
The naive (or basic) approach would be to generate all possible permutations and find the score for each of them. Since there are letters in the English alphabet and three letters in the names, we would be working with
possibilities.
We can keep a running total for the score, and then for each possible name, add to the score:
- for each character in the name, if the character is a vowel, add
to the score;
- for each character in the name, if the index of the character within the alphabet (e.g., 'a' = 0, 'b' = 1, etc.) is divisible by
, then add
to the score; and
- if the name starts with the first five letters of the alphabet (e.g., 'a', 'b', 'c', 'd', 'e'), then add
to the score.
Then, since we want to find the average score over all possibilities, we divide the total score by to get our final result for that round.
For each round, we have three loops, making the algorithm where
is the size of our alphabet (in this case, it's
) and
is the length of the name (which is
). Given we have
rounds of games, we would end up with an
algorithm!
While this method was allowed during the contest, it is not a particularly efficient one, due to generating all permutations of the name and calculating the score for every possibility.
The Efficient Approach
By doing a bit of maths, we can turn the algorithm to just
. Wow!
When assigning points for , we observe that there are only
vowels out of the
possible letters in the alphabet for each of the
characters in the name. And as we saw before, there are
permutations. As such, the total (unadjusted) score when considering
is:
Next, when assigning points for , we consider the fact that every third letter out of the
letters we have in the alphabet is valid. Consequently, for each name, a third of the names are valid. This means we can take total permutations and divide it by
:
Then, when assigning points for , only the first character in the name can be the first
letters in the alphabet. This means that there are
possible names that follow the rule. As such, the total unadjusted score when considering
is:
Since the scores we've just obtained are total scores, we need to average them out by dividing by :
Since these arithmetic operations are constant time, for rounds, we end up with a time complexity of
— a big improvement over the naive implementation. These solutions can be
space additionally, as we can process and output while taking the input of
.
Naive C++ solution:
#include <bits/stdc++.h>
using namespace std;
bool is_vowel(int x) {
return x == 'a'-'a' || x == 'e'-'a' || x == 'i'-'a' || x == 'o'-'a' || x == 'u'-'a';
}
int main() {
int n;
cin >> n;
while (n--) {
int a,b,c;
cin >> a >> b >> c;
long long score = 0;
for (int i = 0; i < 26; i++) {
for (int j = 0; j < 26; j++) {
for (int k = 0; k < 26; k++) {
score += a*(is_vowel(i)+is_vowel(j)+is_vowel(k));
score += b*((i+j+k)%3 == 0);
score += c*(i < 5);
}
}
}
cout << fixed << setprecision(2) << (double)score/(26.0*26.0*26.0) << endl;
}
}
Efficient C++ solution:
#include <bits/stdc++.h>
using namespace std;
const int as = 3*5*26*26;
const int bs = 26*26*26/3;
const int cs = 5*26*26;
int main() {
int n;
cin >> n;
int a,b,c;
while (n--) {
cin >> a >> b >> c;
cout << fixed << setprecision(2) << (double)(a*as + b*bs + c*cs)/(26.0*26.0*26.0) << endl;
}
}
Python solution: Please excuse my Pythonic style
n = int(input())
AS = 3 * 5 * 26 * 26
BS = 26 * 26 * 26 // 3
CS = 5 * 26 * 26
print(
*[
"{:.2f}".format((a * AS + b * BS + c * CS) / (26.0 * 26.0 * 26.0))
for a, b, c in [map(int, input().split()) for _ in range(n)]
],
sep="\n",
)
Comments