#0: K = 49. One possible vector is {"little", "limak"}: 4*6+5*5 = 49. #1: K = 15. One possible vector is {"azz", "xyz"}. #2: K = 704. One possible vector is {"aaaaaaaaaa", "abcdefghijklmnopqrstuvwxyz", "aabbcc" }. #3: K = 37521. One possible vector is "aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyy" repeated 30 times, followed by { "abcd", "aa", "a", "a", "a" }. #4: K = 1. One possible vector is {"a"}.
UNIX> g++ -o grader Grader.cppNow if you pipe the output of a.out into grader, it will test it to make sure it's correct.
Like the Cryptography Problem, I have a shell script tests.sh, that you can use to test your program. When you run tests.sh, your answer should be identical to answers.txt.
Now, how do we construct this last string? We'd like it to have a large score, because that way we'll be subtracting a lot from K, and hopefully we'll terminate in 50 iterations or less.
Here's the approach I took. Take a look at the following string:
s = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx"This string has a maximum score of all strings 50 characters or fewer. The score is 1300. If this string is ≤ K, then this is a good string to start with, because it will subtract the maximum amount from K. Keep doing this until K is less than 1300. You'll note that K's maximum value is 50,000, which, when divided by 1300 is 38, so as long as you can solve smaller values of K in 12 iterations or fewer, you can solve the problem.
When K is less than 1300, what I did was repeatedly remove the last character from s, calculate its score, and see if I could use that. If you think about it, that reduces K's value to under 50 in almost every case. (I'm going to let you think about that on your own). I will assert that when K is less than 1300, you'll need a maximum of three strings whose scores sum to K if you do it in this way. Again, I'll let you prove that assertion on your own time. That gives you an approach to solve the problem. Let me summarize:
/* Topcoder SRM 708, D2 500-pointer * BuildingStrings * James S. Plank * Mon Feb 20 15:59:09 EST 2017 */ #include <string> #include <vector> #include <iostream> #include <cstdio> #include <cstdlib> using namespace std; typedef vector <string> SVec; class BuildingStrings { public: vector <string> findAny(int K); }; vector <string> BuildingStrings::findAny(int K) { int i, score; vector <string> rv; string s; /* Create the string s */ for (i = 0; i < 50; i++) s.push_back('a' + i%26); /* Do steps 2 and 3 from the writeup -- while s's score is less than or equal to K, add it to the return vector and decrement the score from K. While s's score is greater than K, remove the last letter from s. Do this until K <= 50. */ while (K > 50) { score = (s.size() > 26) ? (26 * s.size()) : (s.size() * s.size()); while (score <= K) { rv.push_back(s); K -= score; } s.pop_back(); } /* Step 4: K is <= 50, so you can create a string of length K with a single character. Its score will be K. */ if (K > 0) { s.clear(); s.resize(K, 'a'); rv.push_back(s); } return rv; } |