├── euler-0001.cpp ├── euler-0002.cpp ├── euler-0003.cpp ├── euler-0004.cpp ├── euler-0005.cpp ├── euler-0006.cpp ├── euler-0007.cpp ├── euler-0008.cpp ├── euler-0009.cpp ├── euler-0010.cpp ├── euler-0011.cpp ├── euler-0012.cpp ├── euler-0013.cpp ├── euler-0014.cpp ├── euler-0015.cpp ├── euler-0016.cpp ├── euler-0017.cpp ├── euler-0018.cpp ├── euler-0019.cpp ├── euler-0020.cpp ├── euler-0021.cpp ├── euler-0022.cpp ├── euler-0023.cpp ├── euler-0024.cpp ├── euler-0025.cpp ├── euler-0026.cpp ├── euler-0027.cpp ├── euler-0028.cpp ├── euler-0029.cpp ├── euler-0030.cpp ├── euler-0031.cpp ├── euler-0032.cpp ├── euler-0033.cpp ├── euler-0034.cpp ├── euler-0035.cpp ├── euler-0036.cpp ├── euler-0037.cpp ├── euler-0038.cpp ├── euler-0039.cpp ├── euler-0040.cpp ├── euler-0041.cpp ├── euler-0042.cpp ├── euler-0043.cpp ├── euler-0044.cpp ├── euler-0045.cpp ├── euler-0046.cpp ├── euler-0047.cpp ├── euler-0048.cpp ├── euler-0049.cpp ├── euler-0050.cpp ├── euler-0051.cpp ├── euler-0052.cpp ├── euler-0053.cpp ├── euler-0054.cpp ├── euler-0055.cpp ├── euler-0056.cpp ├── euler-0057.cpp ├── euler-0058.cpp ├── euler-0059.cpp ├── euler-0060.cpp ├── euler-0061.cpp ├── euler-0062.cpp ├── euler-0063.cpp ├── euler-0064.cpp ├── euler-0065.cpp ├── euler-0066.cpp ├── euler-0067.cpp ├── euler-0068.cpp ├── euler-0069.cpp ├── euler-0070.cpp ├── euler-0071.cpp ├── euler-0072.cpp ├── euler-0073.cpp ├── euler-0074.cpp ├── euler-0075.cpp ├── euler-0076.cpp ├── euler-0077.cpp ├── euler-0078.cpp ├── euler-0079.cpp ├── euler-0080.cpp ├── euler-0081.cpp ├── euler-0082.cpp ├── euler-0083.cpp ├── euler-0084.cpp ├── euler-0085.cpp ├── euler-0086.cpp ├── euler-0087.cpp ├── euler-0088.cpp ├── euler-0089.cpp ├── euler-0090.cpp ├── euler-0091.cpp ├── euler-0092.cpp ├── euler-0093.cpp ├── euler-0094.cpp ├── euler-0095.cpp ├── euler-0096.cpp ├── euler-0097.cpp ├── euler-0098.cpp ├── euler-0099.cpp ├── euler-0100.cpp ├── euler-0101.cpp ├── euler-0102.cpp ├── euler-0103.cpp ├── euler-0104.cpp ├── euler-0105.cpp ├── euler-0106.cpp ├── euler-0107.cpp ├── euler-0108.cpp ├── euler-0109.cpp ├── euler-0110.cpp ├── euler-0111.cpp ├── euler-0112.cpp ├── euler-0113.cpp ├── euler-0114.cpp ├── euler-0115.cpp ├── euler-0116.cpp ├── euler-0117.cpp ├── euler-0118.cpp ├── euler-0119.cpp ├── euler-0120.cpp ├── euler-0121.cpp ├── euler-0122.cpp ├── euler-0123.cpp ├── euler-0124.cpp ├── euler-0125.cpp ├── euler-0126.cpp ├── euler-0127.cpp ├── euler-0128.cpp ├── euler-0129.cpp ├── euler-0130.cpp ├── euler-0131.cpp ├── euler-0132.cpp ├── euler-0133.cpp ├── euler-0134.cpp ├── euler-0135.cpp ├── euler-0136.cpp ├── euler-0137.cpp ├── euler-0138.cpp ├── euler-0139.cpp ├── euler-0141.cpp ├── euler-0142.cpp ├── euler-0144.cpp ├── euler-0145.cpp ├── euler-0146.cpp ├── euler-0147.cpp ├── euler-0148.cpp ├── euler-0149.cpp ├── euler-0150.cpp ├── euler-0151.cpp ├── euler-0152.cpp ├── euler-0154.cpp ├── euler-0155.cpp ├── euler-0156.cpp ├── euler-0158.cpp ├── euler-0159.cpp ├── euler-0160.cpp ├── euler-0161.cpp ├── euler-0162.cpp ├── euler-0163.cpp ├── euler-0164.cpp ├── euler-0165.cpp ├── euler-0166.cpp ├── euler-0168.cpp ├── euler-0169.cpp ├── euler-0170.cpp ├── euler-0171.cpp ├── euler-0172.cpp ├── euler-0173.cpp ├── euler-0174.cpp ├── euler-0178.cpp ├── euler-0179.cpp ├── euler-0181.cpp ├── euler-0182.cpp ├── euler-0183.cpp ├── euler-0185.cpp ├── euler-0186.cpp ├── euler-0187.cpp ├── euler-0188.cpp ├── euler-0189.cpp ├── euler-0190.cpp ├── euler-0191.cpp ├── euler-0193.cpp ├── euler-0196.cpp ├── euler-0197.cpp ├── euler-0199.cpp ├── euler-0200.cpp ├── euler-0201.cpp ├── euler-0203.cpp ├── euler-0204.cpp ├── euler-0205.cpp ├── euler-0206.cpp ├── euler-0207.cpp ├── euler-0208.cpp ├── euler-0209.cpp ├── euler-0211.cpp ├── euler-0213.cpp ├── euler-0214.cpp ├── euler-0215.cpp ├── euler-0216.cpp ├── euler-0218.cpp ├── euler-0219.cpp ├── euler-0222.cpp ├── euler-0225.cpp ├── euler-0226.cpp ├── euler-0227.cpp ├── euler-0229.cpp ├── euler-0230.cpp ├── euler-0231.cpp ├── euler-0232.cpp ├── euler-0234.cpp ├── euler-0235.cpp ├── euler-0237.cpp ├── euler-0239.cpp ├── euler-0240.cpp ├── euler-0243.cpp ├── euler-0244.cpp ├── euler-0247.cpp ├── euler-0248.cpp ├── euler-0249.cpp ├── euler-0259.cpp ├── euler-0260.cpp ├── euler-0265.cpp ├── euler-0266.cpp ├── euler-0267.cpp ├── euler-0268.cpp ├── euler-0273.cpp ├── euler-0274.cpp ├── euler-0277.cpp ├── euler-0278.cpp ├── euler-0279.cpp ├── euler-0280.cpp ├── euler-0284.cpp ├── euler-0286.cpp ├── euler-0287.cpp ├── euler-0288.cpp ├── euler-0290.cpp ├── euler-0291.cpp ├── euler-0293.cpp ├── euler-0297.cpp ├── euler-0300.cpp ├── euler-0301.cpp ├── euler-0303.cpp ├── euler-0304.cpp ├── euler-0306.cpp ├── euler-0307.cpp ├── euler-0308.cpp ├── euler-0309.cpp ├── euler-0310.cpp ├── euler-0313.cpp ├── euler-0315.cpp ├── euler-0317.cpp ├── euler-0321.cpp ├── euler-0323.cpp ├── euler-0324.cpp ├── euler-0327.cpp ├── euler-0329.cpp ├── euler-0333.cpp ├── euler-0336.cpp ├── euler-0341.cpp ├── euler-0343.cpp ├── euler-0345.cpp ├── euler-0346.cpp ├── euler-0347.cpp ├── euler-0348.cpp ├── euler-0349.cpp ├── euler-0351.cpp ├── euler-0358.cpp ├── euler-0359.cpp ├── euler-0363.cpp ├── euler-0371.cpp ├── euler-0375.cpp ├── euler-0381.cpp ├── euler-0386.cpp ├── euler-0387.cpp ├── euler-0393.cpp ├── euler-0401.cpp ├── euler-0407.cpp ├── euler-0411.cpp ├── euler-0412.cpp ├── euler-0418.cpp ├── euler-0425.cpp ├── euler-0429.cpp ├── euler-0455.cpp ├── euler-0458.cpp ├── euler-0473.cpp ├── euler-0485.cpp ├── euler-0491.cpp ├── euler-0493.cpp ├── euler-0500.cpp ├── euler-0501.cpp ├── euler-0504.cpp ├── euler-0510.cpp ├── euler-0516.cpp ├── euler-0518.cpp ├── euler-0523.cpp ├── euler-0539.cpp ├── euler-0549.cpp ├── euler-0563.cpp ├── euler-0565.cpp ├── euler-0571.cpp ├── euler-0577.cpp ├── euler-0581.cpp ├── euler-0587.cpp ├── euler-0601.cpp ├── euler-0607.cpp ├── euler-0610.cpp ├── euler-0611.cpp ├── euler-0612.cpp ├── euler-0613.cpp ├── euler-0615.cpp ├── p011_matrix.extra.txt ├── p013_numbers.extra.txt ├── p018_triangle.extra.txt ├── p022_names.txt ├── p042_words.txt ├── p054_poker.txt ├── p059_cipher.txt ├── p067_triangle.txt ├── p079_keylog.txt ├── p081_matrix.txt ├── p082_matrix.txt ├── p083_matrix.txt ├── p089_roman.txt ├── p096_sudoku.txt ├── p098_words.txt ├── p099_base_exp.txt ├── p102_triangles.txt ├── p105_sets.txt ├── p107_network.txt ├── p424_kakuro200.txt └── readme.md /euler-0001.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Multiples of 3 and 5 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=1 7 | // http://euler.stephan-brumme.com/1/ 8 | // 9 | // # Problem 10 | // If we list all the natural numbers below 10 that are multiples of 3 or 5, 11 | // we get 3, 5, 6 and 9. The sum of these multiples is 23. 12 | // 13 | // Find the sum of all the multiples of 3 or 5 below 1000. 14 | // 15 | // # Solved by 16 | // Stephan Brumme 17 | // February 2017 18 | // 19 | // # Algorithm 20 | // We are supposed to find of all multiples of 3 or 5 __below__ the input number, 21 | // therefore we decrement it by one. 22 | // 23 | // In general, the sum of all numbers between 1 and `x` is `sum_{1..x}i=x * (x+1)/2` 24 | // (see https://en.wikipedia.org/wiki/Triangular_number ) 25 | // 26 | // There are `floor{x/3}` numbers between 1 and x which are divisible by 3 (assuming `floor{x/3}` is an integer division). 27 | // e.g. the range `1..10` contains `floor{10/3}=3` such numbers (it's 3, 6 and 9). Their sum is `3+6+9=18`. 28 | // This can be written as `3/3 * (3+6+9)` which is the same as `3 * (3/3+6/3+9/3)=3 * (1+2+3)`. 29 | // Those brackets represent ` sum_{1..3}i = sum_{1..10/3}i` (or short: ` sum{10/3}`) 30 | // and thus our overall formula for the sum of all multiples of 3 becomes `3 * sum{x/3}`. 31 | // 32 | // The same formula can be used for 5: 33 | // The sum of all numbers divisible by 5 is `5 * sum{x/5}` 34 | // 35 | // However, there are numbers divisible by 3 __and__ 5, which means they are part of __both__ sums. 36 | // We must not count them twice, that's why we (in addition to the aforementioned sums) 37 | // compute the sum of all numbers divisible by 3*5=15 to correct for this error. 38 | // 39 | // In the end we print ''sumThree + sumFive - sumFifteen'' 40 | // 41 | // # Alternative 42 | // Looping through all numbers from 1 and 1000 and checking each of those numbers 43 | // whether they are divisible by 3 or 5 easily solves the problem, too, and produces the result pretty much instantly. 44 | // Even more, the code will be probably a bit shorter. 45 | // 46 | // However, Hackerrank's input numbers are too large for that simple approach (up to `10^9` with `10^5` test cases) 47 | // and will lead to timeouts. 48 | 49 | #include 50 | 51 | // triangular number: `sum{x}=1+2+..+x = x*(x+1)/2` 52 | unsigned long long sum(unsigned long long x) 53 | { 54 | return x * (x + 1) / 2; 55 | } 56 | 57 | int main() 58 | { 59 | unsigned int tests; 60 | std::cin >> tests; 61 | while (tests--) 62 | { 63 | unsigned long long last; 64 | std::cin >> last; 65 | 66 | // not including that number 67 | last--; 68 | 69 | // find sum of all numbers divisible by 3 or 5 70 | auto sumThree = 3 * sum(last / 3); 71 | auto sumFive = 5 * sum(last / 5); 72 | 73 | // however, those numbers divisible by 3 AND 5 will be counted twice 74 | auto sumFifteen = 15 * sum(last / 15); 75 | 76 | std::cout << (sumThree + sumFive - sumFifteen) << std::endl; 77 | } 78 | 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /euler-0002.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Even Fibonacci numbers 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=2 7 | // http://euler.stephan-brumme.com/2/ 8 | // 9 | // # Problem 10 | // Each new term in the Fibonacci sequence is generated by adding the previous two terms. 11 | // By starting with 1 and 2, the first 10 terms will be: 12 | // 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... 13 | // By considering the terms in the Fibonacci sequence whose values do not exceed four million, 14 | // find the sum of the even-valued terms. 15 | // 16 | // # Solved by 17 | // Stephan Brumme 18 | // February 2017 19 | // 20 | // # Algorithm 21 | // As explained in the problem statement, you can compute all Fibonacci numbers in an iterative way: 22 | // `F_i=F_{i-2}+F_{i-1}` 23 | // 24 | // My variables ''a'' and ''b'' stand for `F_{i-2}` and `F_{i-1}` whereas ''next'' is `F_i` 25 | // After each iteration, ''next=a+b'' and then ''a'' becomes ''b'' and ''b'' becomes ''next''. 26 | // 27 | // A number is even if there is no remainder when divided by 2. 28 | // In most programming languages it's written as ''variable % 2 == 0'' 29 | // 30 | // Internally, your compiler might translate this to the more efficient ''(variable & 1) == 0'' 31 | // 32 | // # Note 33 | // ''unsigned long long'' is required to pass all Hackerrank tests. 34 | 35 | #include 36 | 37 | int main() 38 | { 39 | unsigned int tests; 40 | std::cin >> tests; 41 | while (tests--) 42 | { 43 | unsigned long long last; 44 | std::cin >> last; 45 | 46 | unsigned long long sum = 0; 47 | // first Fibonacci numbers 48 | unsigned long long a = 1; 49 | unsigned long long b = 2; 50 | 51 | // until we reach the limit 52 | while (b <= last) 53 | { 54 | // even ? 55 | if (b % 2 == 0) 56 | sum += b; 57 | 58 | // next Fibonacci number 59 | auto next = a + b; 60 | a = b; 61 | b = next; 62 | } 63 | 64 | std::cout << sum << std::endl; 65 | } 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /euler-0003.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Largest prime factor 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=3 7 | // http://euler.stephan-brumme.com/3/ 8 | // 9 | // # Problem 10 | // The prime factors of 13195 are 5, 7, 13 and 29. 11 | // What is the largest prime factor of the number 600851475143 ? 12 | // 13 | // # Solved by 14 | // Stephan Brumme 15 | // February 2017 16 | // 17 | // # Algorithm 18 | // Each composite number `x` can be represented as the product of at least two factors: `x=factor*other` 19 | // If we assume that `factor` is a prime number and `factor<=other`, then there are two options: 20 | // 1. `other` can be a prime number, too 21 | // 2. `other` is composite 22 | // 23 | // In case 1, `other` is the largest prime - and we are done. 24 | // In case 2, we can continue the same process by setting set `x=other`. 25 | // After some iterations we will hit case 1. 26 | // 27 | // Therefore I start a loop beginning with `factor=2` (the smallest prime) 28 | // and as long as our number `x` can be divided by `factor` with remainder 0: 29 | // - divide `x` by `factor`, but abort if `x==factor` because then we have found our largest prime factor. 30 | // 31 | // We can abort as soon as all `factor<=sqrt{x}` are processed because then only a prime is left. 32 | // 33 | // # Note 34 | // You may have noticed that `factor` isn't always a prime number in my program: 35 | // yes, I simply scan through all numbers, even composite ones. 36 | // 37 | // But if they are composite, then I already checked all smaller primes. 38 | // That means, I checked all prime factors of that composite number, too. 39 | // Therefore `x` can't be divided by a composite `factor` with remainder 0 because 40 | // all required prime factors were already eliminated from `x`. 41 | // 42 | // In short: those divisions by composite numbers always fail but my program is still fast enough and 43 | // writing a proper prime sieve doesn't give a significant speed boost for this problem. 44 | 45 | #include 46 | 47 | int main() 48 | { 49 | unsigned int tests; 50 | std::cin >> tests; 51 | while (tests--) 52 | { 53 | unsigned long long x; 54 | std::cin >> x; 55 | 56 | // x can be represented by x=factor*otherFactor 57 | // where factor <= otherFactor 58 | // therefore factor <= sqrt(x) 59 | for (unsigned long long factor = 2; factor * factor <= x; factor++) 60 | // remove factor, actually it's a prime 61 | // (can occur multiple times, e.g. 20=2*2*5) 62 | while (x % factor == 0 && x != factor) // note: keep last prime 63 | x /= factor; 64 | 65 | std::cout << x << std::endl; 66 | } 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /euler-0004.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Largest palindrome product 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=4 7 | // http://euler.stephan-brumme.com/4/ 8 | // 9 | // # Problem 10 | // A palindromic number reads the same both ways. 11 | // The largest palindrome made from the product of two 2-digit numbers is `9009 = 91 * 99`. 12 | // Find the largest palindrome made from the product of two 3-digit numbers. 13 | // 14 | // # Solved by 15 | // Stephan Brumme 16 | // February 2017 17 | // 18 | // # Algorithm 19 | // The upper three digits of such a six-digit palindrome are a "mirrored" version of the lower three digits. 20 | // I wrote a function ''makePalindrome'' which takes a three-digit number and returns its six-digit palindrome. 21 | // 22 | // There are only 899 six-digit palindromes because the upper three digits must be 100 ... 999 23 | // (no leading zeros allowed because then it wouldn't be a six-digit number anymore). 24 | // 25 | // Beginning with 999, I loop "downwards" through all possible combinations trying to find a three-digit divisor. 26 | // A simple speedup is achieved by observing that at least one divisor `i` must be `i>=100` and `i^2<=palindrome`. 27 | // 28 | // # Hackerrank 29 | // Hackerrank's problem asks for a variable maximum upper limit. It's 999999 for the original problem. 30 | // 31 | // # Note 32 | // I create six-digit palindromes by splitting a three-digit numbers into its single digits. 33 | // A possible alternative is to convert the three-digit number into a string and concatenate it with its reversed version. 34 | // However, often those string operations tend to be quite slow. 35 | 36 | #include 37 | 38 | // convert 3 digits to a 6 digit palindrome by mirroring and appending these 3 digits 39 | // e.g. 234 becomes 234432 40 | unsigned int makePalindrome(unsigned int x) 41 | { 42 | unsigned int result = x * 1000; // abc => abc000 43 | result += x / 100; // a.. => a..00a 44 | result += ((x / 10) % 10) * 10; // .b. => .b.0b. 45 | result += (x % 10) * 100; // ..c => ..cc.. 46 | return result; 47 | } 48 | 49 | int main() 50 | { 51 | unsigned int tests; 52 | std::cin >> tests; 53 | while (tests--) 54 | { 55 | // Hackerrank has a variable upper limit (instead of 1000000) 56 | unsigned int maximum; 57 | std::cin >> maximum; 58 | 59 | bool found = false; 60 | // find all palindromes, beginning with the largest 61 | // walk through all three-digit numbers 62 | for (auto upper3 = maximum / 1000; upper3 >= 100 && !found; upper3--) 63 | { 64 | // "mirror" these three digits to create a six-digit palindrome 65 | auto palindrome = makePalindrome(upper3); 66 | // too big ? 67 | if (palindrome >= maximum) 68 | continue; 69 | 70 | // split into two factors 71 | for (unsigned int i = 100; i * i <= palindrome; i++) 72 | if (palindrome % i == 0) // divisible ? 73 | { 74 | // make sure both factors must have three digits 75 | auto other = palindrome / i; 76 | if (other < 100 || other > 999) 77 | continue; 78 | 79 | std::cout << palindrome << std::endl; 80 | found = true; 81 | break; 82 | } 83 | } 84 | } 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /euler-0005.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Smallest multiple 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=5 7 | // http://euler.stephan-brumme.com/5/ 8 | // 9 | // # Problem 10 | // 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. 11 | // What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20? 12 | // 13 | // # Solved by 14 | // Stephan Brumme 15 | // February 2017 16 | // 17 | // # Algorithm 18 | // Basically we have to find the Least Common Multiple of 1,2,..,20 (abbreviated as `lcm`, see https://en.wikipedia.org/wiki/Least_common_multiple ). 19 | // In general, the `lcm` of two numbers `a` and `b` can be computed as: `lcm(a,b)=frac{ab}{gcd(a,b)}` 20 | // 21 | // `gcd` stands for the Greatest Common Divisor (see https://en.wikipedia.org/wiki/Greatest_common_divisor ). 22 | // 23 | // Euclid's algorithm ( https://en.wikipedia.org/wiki/Euclidean_algorithm ) produces the `gcd` in a recursive way: 24 | // `gcd(a,0) = 0` 25 | // `gcd(a,b) = gcd(b mod a, a)` 26 | // 27 | // An iterative version in C++ consists of just a few lines, see my ''gcd'' function. 28 | // 29 | // Now that we know how to determine `lcm(a,b)` there is a pretty easy way to do the same for `lcm(x_1,x_2,x_3,...,x_n)`: 30 | // `lcm(x_1,x_2,x_3,...,x_{n-1},x_n) = lcm(lcm(x_1,x_2,x_3,...,x_{n-1}), x_n)` 31 | // 32 | // Example: 33 | // `lcm(1,2,3,4)` 34 | // `=lcm(lcm(1,2,3),4)` 35 | // `=lcm(lcm(lcm(1,2),3),4)` 36 | // `=lcm(lcm(2,3),4)` 37 | // `=lcm(6,4)` 38 | // `=12` 39 | // 40 | // # Note 41 | // Wikipedia lists some interesting alternatives with different runtime behavior. 42 | // Especially the binary algorithm can be much faster (at the cost of more code). 43 | // 44 | // By the way: the G++ compiler offers an intrinsic called ''__gcd()'' which may be faster on some systems. 45 | // I highly suspect it is based on the binary algorithm. 46 | 47 | #include 48 | 49 | // greatest common divisor 50 | unsigned long long gcd(unsigned long long a, unsigned long long b) 51 | { 52 | while (a != 0) 53 | { 54 | unsigned long long c = a; 55 | a = b % a; 56 | b = c; 57 | } 58 | return b; 59 | } 60 | 61 | // least common multiple 62 | unsigned long long lcm(unsigned long long a, unsigned long long b) 63 | { 64 | // parenthesis avoid overflow 65 | return a * (b / gcd(a, b)); 66 | } 67 | 68 | int main() 69 | { 70 | unsigned int tests; 71 | std::cin >> tests; 72 | while (tests--) 73 | { 74 | unsigned int x; 75 | std::cin >> x; 76 | 77 | // find least common multiple of all numbers 78 | unsigned long long result = 1; 79 | for (unsigned int i = 2; i <= x; i++) 80 | result = lcm(result, i); 81 | 82 | std::cout << result << std::endl; 83 | } 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /euler-0006.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Sum square difference 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=6 7 | // http://euler.stephan-brumme.com/6/ 8 | // 9 | // # Problem 10 | // The sum of the squares of the first ten natural numbers is, 11 | // `1^2 + 2^2 + ... + 10^2 = 385` 12 | // 13 | // The square of the sum of the first ten natural numbers is, 14 | // `(1 + 2 + ... + 10)^2 = 55^2 = 3025` 15 | // 16 | // Hence the difference between the sum of the squares of the first ten natural numbers 17 | // and the square of the sum is `3025 - 385 = 2640`. 18 | // 19 | // Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum. 20 | // 21 | // # Solved by 22 | // Stephan Brumme 23 | // February 2017 24 | // 25 | // # Algorithm 26 | // A very simple problem: 27 | // - a ''for''-loop adds all natural numbers (''sum'') and their squares (''sumSquared''). 28 | // - finally ''squaredSum=sum*sum'' 29 | // - and print the difference between ''squaredSum - sumSquared'' 30 | // 31 | // The only minor hiccup was to switch from ''int'' to ''long long'' (basically from 32 to 64 bits). 32 | // 33 | // # Alternative 34 | // The series of sums of all natural numbers are the so-called Triangular numbers ( https://en.wikipedia.org/wiki/Triangular_number ). 35 | // They have a closed form, too: 36 | // `sum{x}=frac{x(x+1)}{2}` 37 | // 38 | // And there is a closed form for the sum of squares as well ( https://en.wikipedia.org/wiki/Square_pyramidal_number ) 39 | // `sum{x^2}=frac{x(x+1)(2x+1)}{6}` 40 | // 41 | // I can easily derive the formula for triangular numbers but the one for the sum of squares isn't 42 | // that obvious to me - I had to look it up. 43 | // 44 | // Therefore it would feel like cheating when using the closed form in my code without further explanation ... 45 | // and the simple ''for''-loop is fast enough to pass all tests, too. 46 | 47 | #include 48 | 49 | int main() 50 | { 51 | unsigned int tests; 52 | std::cin >> tests; 53 | while (tests--) 54 | { 55 | unsigned long long x; 56 | std::cin >> x; 57 | 58 | unsigned long long sum = 0; // 1 + 2 + ... 59 | unsigned long long sumSquared = 0; // 1^2 + 2^2 + ... 60 | 61 | for (unsigned long long i = 1; i <= x; i++) 62 | { 63 | sum += i; 64 | sumSquared += i*i; 65 | } 66 | // chances are that your compiler (partially) unrolls this simple loop 67 | 68 | // actually we don't need a loop for the sum (and the sum of squares) 69 | // => see "Alternative" section above 70 | 71 | // we had (1+2+...) instead of (1+2+...)^2 72 | unsigned long long squaredSum = sum * sum; 73 | std::cout << (squaredSum - sumSquared) << std::endl; 74 | } 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /euler-0007.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // 10001st prime 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=7 7 | // http://euler.stephan-brumme.com/7/ 8 | // 9 | // # Problem 10 | // By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13. 11 | // What is the 10001st prime number? 12 | // 13 | // # Solved by 14 | // Stephan Brumme 15 | // February 2017 16 | // 17 | // # Algorithm 18 | // A prime number is an integer number `p>=2` that can only be divided by `1` and by itself (`p`). 19 | // 2 is the smallest prime number and the only even prime number, too (all other prime numbers are odd). 20 | // 21 | // Each number `x` can be split into its prime factors, that means we check for all primes `p=sqrt{x}` (which is `p^2>=x`) to speed up the program. 26 | // 27 | // And since all primes are odd - __except for 2__ - I simply add 2 to the list of primes and then scan 28 | // only odd numbers, beginning with 3 (and increment 2). 29 | // 30 | // # Alternative 31 | // Take a look at my [toolbox](../toolbox/) for other prime sieves or even precomputed lookup tables. 32 | // 33 | // Wikipedia lists a few faster algorithms ( https://en.wikipedia.org/wiki/Prime_number ), too. 34 | // On my website http://create.stephan-brumme.com/eratosthenes/ you can find parallelized code that computes 35 | // all 50847534 prime numbers below 1 billion in less than a second. 36 | // 37 | // # I/O 38 | // echo "1 10001" | ./euler-0007 39 | 40 | #include 41 | #include 42 | 43 | int main() 44 | { 45 | // compute the first 10001 primes 46 | std::vector primes; 47 | primes.reserve(10001); 48 | primes.push_back(2); 49 | for (unsigned int x = 3; primes.size() <= 10000; x += 2) 50 | { 51 | bool isPrime = true; 52 | for (auto p : primes) 53 | { 54 | // found a divisor ? => abort 55 | if (x % p == 0) 56 | { 57 | isPrime = false; 58 | break; 59 | } 60 | 61 | // no larger prime factors possible ? 62 | if (p*p > x) 63 | break; 64 | } 65 | 66 | // yes, we have a new prime 67 | if (isPrime) 68 | primes.push_back(x); 69 | } 70 | 71 | // processing all test cases is now just a plain lookup 72 | unsigned int tests; 73 | std::cin >> tests; 74 | while (tests--) 75 | { 76 | unsigned int x; 77 | std::cin >> x; 78 | // just look up the x-th prime 79 | // with a little twist: vector's index is zero-based, therefore "off by one" 80 | x--; 81 | 82 | if (x < primes.size()) 83 | std::cout << primes[x] << std::endl; 84 | else 85 | std::cout << "ERROR" << std::endl; 86 | } 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /euler-0009.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Special Pythagorean triplet 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=9 7 | // http://euler.stephan-brumme.com/9/ 8 | // 9 | // # Problem 10 | // A Pythagorean triplet is a set of three natural numbers, `a < b < c`, 11 | // for which, `a^2 + b^2 = c^2` 12 | // 13 | // For example, `3^2 + 4^2 = 9 + 16 = 25 = 5^2`. 14 | // 15 | // There exists exactly one Pythagorean triplet for which `a + b + c = 1000`. 16 | // Find the product `abc`. 17 | // 18 | // # Solved by 19 | // Stephan Brumme 20 | // February 2017 21 | // 22 | // # Algorithm 23 | // I loop through all pairs `a 31 | #include 32 | #include 33 | 34 | int main() 35 | { 36 | // precompute all pairs a cache(MaxPerimeter + 1, NoSolution); 43 | 44 | // scan all pairs a MaxPerimeter) 59 | break; 60 | 61 | // better solution than before ? 62 | if (cache[sum] < a*b*c) 63 | cache[sum] = a*b*c; 64 | } 65 | 66 | unsigned int tests; 67 | std::cin >> tests; 68 | while (tests--) 69 | { 70 | unsigned int n; 71 | std::cin >> n; 72 | // just lookup results (-1 if no solution) 73 | std::cout << cache[n] << std::endl; 74 | } 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /euler-0010.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Summation of primes 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=10 7 | // http://euler.stephan-brumme.com/10/ 8 | // 9 | // # Problem 10 | // The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. 11 | // Find the sum of all the primes below two million. 12 | // 13 | // # Solved by 14 | // Stephan Brumme 15 | // February 2017 16 | // 17 | // # Algorithm 18 | // The prime sieve is more or less unchanged from problem 7. 19 | // Then I create a lookup table ''sums'' which contains for each prime number `p` 20 | // the sum of all prime numbers `<=p`. 21 | // 22 | // The test cases may contain numbers which are not prime, too. 23 | // Therefore I use ''upper_bound'' to find the smallest entry which `>=p`. 24 | // And since we that entry "is one step too far", I go back to the previous entry and print it. 25 | // 26 | // # Hackerrank 27 | // My 2-step design was heavily influenced by Hackerrank's large number of test cases: 28 | // the "expensive" precomputation is done once and the test cases are computationally very "cheap". 29 | 30 | #include 31 | #include 32 | #include 33 | 34 | int main() 35 | { 36 | // prime numbers beyond this are not relevant for the problem 37 | const unsigned int MaxPrime = 2000000; 38 | 39 | // precompute all relevant prime numbers 40 | std::vector primes; 41 | // the only even prime 42 | primes.push_back(2); 43 | // now check all odd numbers for primality 44 | for (unsigned int i = 3; i <= MaxPrime; i += 2) 45 | { 46 | bool isPrime = true; 47 | for (auto p : primes) 48 | { 49 | // no larger prime factor possible ? 50 | if (p*p > i) 51 | break; 52 | 53 | // no prime number ? 54 | if (i % p == 0) 55 | { 56 | isPrime = false; 57 | break; 58 | } 59 | } 60 | 61 | // yes, we have a new prime 62 | if (isPrime) 63 | primes.push_back(i); 64 | } 65 | 66 | // prime numbers were found in ascending order, 67 | // let's add their value and store in a map such that 68 | // [prime number] => [sum of all prime numbers up to the current] 69 | // note: long long is required to avoid overflows 70 | std::map sums; 71 | unsigned long long sum = 0; 72 | for (auto p : primes) 73 | { 74 | sum += p; 75 | sums[p] = sum; 76 | } 77 | 78 | // the test cases are more or less "smart" lookups 79 | unsigned int tests; 80 | std::cin >> tests; 81 | while (tests--) 82 | { 83 | unsigned int x; 84 | std::cin >> x; 85 | 86 | // find the closest prime number which is bigger than the input 87 | auto i = sums.upper_bound(x); 88 | // go back to the closest prime number which is smaller than the input 89 | i--; 90 | 91 | // show the sum associated to that prime number 92 | std::cout << i->second << std::endl; 93 | } 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /euler-0016.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Power digit sum 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=16 7 | // http://euler.stephan-brumme.com/16/ 8 | // 9 | // # Problem 10 | // `2^{15} = 32768` and the sum of its digits is `3 + 2 + 7 + 6 + 8 = 26`. 11 | // 12 | // What is the sum of the digits of the number `2^{1000}`? 13 | // 14 | // # Solved by 15 | // Stephan Brumme 16 | // February 2017 17 | // 18 | // # Algorithm 19 | // These two equations describe the iterative computation of `2^x`: 20 | // `2^0 = 1` and `2^x = 2 * 2^{x-1}` 21 | // 22 | // These numbers grow pretty big and for `x=64` exceed the range of ''unsigned long long''. 23 | // That's why I store all decimal ''Digits'' in a ''std::vector'', where the lowest index contains the least significant digits. 24 | // 25 | // For `x=0` - which represents `2^0 = 1` - this ''Digits'' container's elements are ''{ 1 }'' 26 | // For `x=15` - which represents `2^{15} = 1` - this ''Digits'' container's elements are ''{ 8, 6, 7, 2, 3 }'' 27 | // 28 | // Multiplying ''Digits'' by 2 follows the same rules as basic multiplication taught in school: 29 | // 1. multiply each digit by 2, start at the lowest digit 30 | // 2. if `digit * 2 >= 10` then an overflow occurred: carry over `(digit * 2) div 10` to the next digit and keep `(digit * 2) mod 10`. 31 | // __Note:__ we must carry over at most 1 and instead of a computationally expensive modulo we can subtract 10 which is faster 32 | // 33 | // # Hackerrank 34 | // To avoid timeouts, I store all results (even intermediate steps) in a cache and re-use as much as possible from this cache. 35 | // 36 | // # Alternative 37 | // [Exponentation by squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring) saves many steps: 38 | // The result of `2^1024` can be found in just 10 steps instead of 1024. 39 | 40 | #include 41 | #include 42 | 43 | // store single digits in an array, lowest digit come first 44 | typedef std::vector Digits; 45 | 46 | int main() 47 | { 48 | // memoize powers of two 49 | std::vector cache; 50 | // add 2^0 = 1 51 | cache.push_back({ 1 }); 52 | 53 | unsigned int tests; 54 | std::cin >> tests; 55 | while (tests--) 56 | { 57 | unsigned int exponent; 58 | std::cin >> exponent; 59 | 60 | // and compute the remaining exponents 61 | for (unsigned int current = cache.size(); current <= exponent; current++) 62 | { 63 | auto power = cache.back(); 64 | unsigned int carry = 0; 65 | for (auto& i : power) 66 | { 67 | // times two ... 68 | i = 2 * i + carry; 69 | 70 | // handle overflow 71 | if (i >= 10) 72 | { 73 | i -= 10; 74 | carry = 1; 75 | } 76 | else 77 | { 78 | carry = 0; 79 | } 80 | } 81 | 82 | // still some carry left ? 83 | if (carry != 0) 84 | power.push_back(carry); 85 | 86 | // memoize result 87 | cache.push_back(power); 88 | } 89 | 90 | // sum of all digits 91 | unsigned int sum = 0; 92 | for (auto i : cache[exponent]) 93 | sum += i; 94 | std::cout << sum << std::endl; 95 | } 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /euler-0020.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Factorial digit sum 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=20 7 | // http://euler.stephan-brumme.com/20/ 8 | // 9 | // # Problem 10 | // `n!` means `n * (n - 1) * ... * 3 * 2 * 1` 11 | // 12 | // For example, `10! = 10 * 9 * ... * 3 * 2 * 1 = 3628800`, 13 | // and the sum of the digits in the number `10!` is `3 + 6 + 2 + 8 + 8 + 0 + 0 = 27`. 14 | // 15 | // Find the sum of the digits in the number `100!` 16 | // 17 | // # Solved by 18 | // Stephan Brumme 19 | // February 2017 20 | // 21 | // # Algorithm 22 | // Substantial parts are similar to problem 16. 23 | // The most obvious difference is that ''carry'' may become bigger than 1. 24 | // 25 | // # Hackerrank 26 | // Compared to problem 16, timeouts were no issue and therefore the code is actually more compact. 27 | 28 | #include 29 | #include 30 | 31 | // store single digits in an array, lowest digit come first 32 | typedef std::vector Digits; 33 | 34 | // return factorial 35 | Digits factorial(unsigned int maxFactor) 36 | { 37 | // 1! = 1 38 | Digits result = { 1 }; 39 | 40 | // avoid further memory allocations 41 | result.reserve(2568); // 1000! has 2568 digits 42 | 43 | // go through all factors 44 | for (unsigned int factor = 2; factor <= maxFactor; factor++) 45 | { 46 | // multiply each digit with current factor 47 | // might overflow into next digit => carry 48 | unsigned int carry = 0; 49 | for (auto& digit : result) 50 | { 51 | digit = digit * factor + carry; 52 | 53 | // overflow ? 54 | if (digit >= 10) 55 | { 56 | carry = digit / 10; 57 | digit %= 10; 58 | } 59 | else 60 | carry = 0; 61 | } 62 | 63 | // add remaining carry 64 | while (carry != 0) 65 | { 66 | result.push_back(carry % 10); 67 | carry /= 10; 68 | } 69 | } 70 | return result; 71 | } 72 | 73 | int main() 74 | { 75 | unsigned int tests; 76 | std::cin >> tests; 77 | while (tests--) 78 | { 79 | unsigned int number; 80 | std::cin >> number; 81 | 82 | // add all digits of the factorial 83 | unsigned int sum = 0; 84 | for (auto i : factorial(number)) 85 | sum += i; 86 | std::cout << sum << std::endl; 87 | } 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /euler-0021.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Amicable numbers 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=21 7 | // http://euler.stephan-brumme.com/21/ 8 | // 9 | // # Problem 10 | // Let `d(n)` be defined as the sum of proper divisors of `n` (numbers less than `n` which divide evenly into `n`). 11 | // If `d(a) = b` and `d(b) = a`, where `a!=b`, then `a` and `b` are an amicable pair 12 | // and each of `a` and `b` are called amicable numbers. 13 | // 14 | // For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore `d(220) = 284`. 15 | // The proper divisors of 284 are 1, 2, 4, 71 and 142; so `d(284) = 220`. 16 | // 17 | // Evaluate the sum of all the amicable numbers under 10000. 18 | // 19 | // # Solved by 20 | // Stephan Brumme 21 | // February 2017 22 | // 23 | // # Algorithm 24 | // My function ''getSum'' returns the sum of all proper divisors of ''x''. 25 | // The brute-force approach works but turns out to be too slow: a ''for''-loop from 2 to ''x-1''. 26 | // 27 | // But we can easily reduce the number of iterations: 28 | // For each proper divisor `i` of `x` there is another divisor `j=x/i`, except when `i^2=x`. 29 | // More interesting, if we assume `i 41 | #include 42 | 43 | // generate sum of all divisor's of x (where x > 1) 44 | unsigned int getSum(unsigned int x) 45 | { 46 | // find all factors: 47 | // look only for the "smaller" divisors <= sqrt(x) 48 | // and they have a "bigger" brother x / divisor 49 | 50 | // 1 is always a divisor, but not the number x itself 51 | unsigned int divisorSum = 1; 52 | // therefore start at 2 53 | for (unsigned int divisor = 2; divisor * divisor <= x; divisor++) 54 | if (x % divisor == 0) 55 | { 56 | divisorSum += divisor; 57 | 58 | // add the "bigger brother" 59 | auto otherDivisor = x / divisor; 60 | // except square numbers 61 | if (otherDivisor != divisor) 62 | divisorSum += otherDivisor; 63 | } 64 | 65 | return divisorSum; 66 | } 67 | 68 | int main() 69 | { 70 | // contain all numbers which are part of an amicable pair 71 | std::set amicables; 72 | 73 | // precomputation step: 74 | // find all amicable numbers <= 100000 75 | const unsigned int MaxAmicable = 100000; 76 | for (unsigned int i = 2; i <= MaxAmicable; i++) 77 | { 78 | auto sibling = getSum(i); 79 | 80 | // found a pair ? 81 | if (i == getSum(sibling) && i != sibling) 82 | { 83 | amicables.insert(i); 84 | amicables.insert(sibling); 85 | } 86 | } 87 | 88 | // and now start processing input 89 | unsigned int tests; 90 | std::cin >> tests; 91 | while (tests--) 92 | { 93 | unsigned int x; 94 | std::cin >> x; 95 | 96 | // just look up all suitables numbers 97 | unsigned int sum = 0; 98 | for (auto i : amicables) 99 | { 100 | // discard those that are too big 101 | if (i > x) 102 | break; 103 | // note: an set::set is sorted ascendingly by default 104 | 105 | // yes, accept that amicable number 106 | sum += i; 107 | } 108 | 109 | std::cout << sum << std::endl; 110 | } 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /euler-0027.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Quadratic primes 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=27 7 | // http://euler.stephan-brumme.com/27/ 8 | // 9 | // # Problem 10 | // Euler discovered the remarkable quadratic formula: `n^2+n+41` 11 | // 12 | // It turns out that the formula will produce 40 primes for the consecutive integer values `0<=n<=39`. 13 | // However, when `n=40`, `40^2+40+41=40(40+1)+41` is divisible by 41, and certainly when `n=41`, `41^2+41+41` is clearly divisible by 41. 14 | // 15 | // The incredible formula `n^2-79n+1601` was discovered, which produces 80 primes for the consecutive values `0<=n<=79`. 16 | // The product of the coefficients, `-79` and `1601`, is `-126479`. 17 | // 18 | // Considering quadratics of the form: 19 | // `n^2 + a * n + b`, where `|a|<1000` and `|b|<=1000` where `|n|` is the modulus/absolute value of `n` e.g. `|11|=11` and `|-4|=4` 20 | // 21 | // Find the product of the coefficients, `a` and `b`, for the quadratic expression that produces the maximum number of primes for consecutive values of `n`, starting with `n=0`. 22 | // 23 | // # Solved by 24 | // Stephan Brumme 25 | // February 2017 26 | // 27 | // # Algorithm 28 | // Nothing fancy: ''isPrime'' determines whether its parameter is a prime number or not. 29 | // And then two nested loops check every combination of ''a'' and ''b''. 30 | // 31 | // # Note 32 | // ''isPrime'' can be optimized in various ways - but the basic algorithm is fast enough for the problem. 33 | 34 | #include 35 | 36 | // return true if x is prime 37 | bool isPrime(int x) 38 | { 39 | // reject invalid input 40 | if (x <= 1) 41 | return false; 42 | 43 | // process all potential divisors 44 | for (int factor = 2; factor*factor <= x; factor++) 45 | if (x % factor == 0) 46 | return false; 47 | 48 | // no such divisor found, it's a prime number 49 | return true; 50 | } 51 | 52 | int main() 53 | { 54 | // upper and lower limit of the coefficients 55 | int limit; 56 | std::cin >> limit; 57 | // make sure it's a positive number 58 | if (limit < 0) 59 | limit = -limit; 60 | 61 | // keep track of best sequence: 62 | // number of generated primes 63 | unsigned int consecutive = 0; 64 | // its coefficients 65 | int bestA = 0; 66 | int bestB = 0; 67 | 68 | // simple brute-force approach 69 | for (int a = -limit; a <= +limit; a++) 70 | for (int b = -limit; b <= +limit; b++) 71 | { 72 | // count number of consecutive prime numbers 73 | unsigned int length = 0; 74 | while (isPrime(length * length + a * length + b)) 75 | length++; 76 | 77 | // better than before ? 78 | if (consecutive < length) 79 | { 80 | consecutive = length; 81 | bestA = a; 82 | bestB = b; 83 | } 84 | } 85 | 86 | #define ORIGINAL 87 | #ifdef ORIGINAL 88 | // print a*b 89 | std::cout << (bestA * bestB) << std::endl; 90 | #else 91 | // print best factors 92 | std::cout << bestA << " " << bestB << std::endl; 93 | #endif 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /euler-0030.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Digit fifth powers 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=30 7 | // http://euler.stephan-brumme.com/30/ 8 | // 9 | // # Problem 10 | // Surprisingly there are only three numbers that can be written as the sum of fourth powers of their digits: 11 | // 12 | // `1634 = 1^4 + 6^4 + 3^4 + 4^4` 13 | // `8208 = 8^4 + 2^4 + 0^4 + 8^4` 14 | // `9474 = 9^4 + 4^4 + 7^4 + 4^4` 15 | // 16 | // As `1 = 1^4` is not a sum it is not included. 17 | // 18 | // The sum of these numbers is 1634 + 8208 + 9474 = 19316. 19 | // 20 | // Find the sum of all the numbers that can be written as the sum of fifth powers of their digits. 21 | // 22 | // # Solved by 23 | // Stephan Brumme 24 | // February 2017 25 | // 26 | // # Algorithm 27 | // The sum of the digits' fifth powers is maximized when each digit is 9: 28 | // 1 digit: `1 * 9^5 = 59049` 29 | // 2 digits: `2 * 9^5 = 118098` 30 | // 3 digits: `3 * 9^5 = 177147` 31 | // 4 digits: `4 * 9^5 = 236196` 32 | // 5 digits: `5 * 9^5 = 295245` 33 | // 6 digits: `6 * 9^5 = 354294` 34 | // 7 digits: `7 * 9^5 = 413343` 35 | // 36 | // The last line is pretty interesting: it's impossible for a seven-digit number to have a seven-digit sum of its digits' fifth powers, 37 | // because all those sums would have at most six digits. 38 | // 39 | // If we analyse all numbers from 2 to 354294 (maximum sum for 6 digits) then we can solve the problem: 40 | // 1. split each number into its digits 41 | // 2. add all fifth powers of these digits 42 | // 3. if the sum is equal to the original number then add it to our result 43 | // 44 | // # Hackerrank 45 | // The exponent varies between 3 and 6. The maximum number can be computed similar to the table above: 46 | // 7 digits: `7 * 9^6 = 3720087` 47 | // 8 digits: `8 * 9^6 = 4251528` ==> impossible 48 | // 49 | // To simplify the code my loop always stops at 4251528 even though lower numbers would suffice for exponents < 6. 50 | // Timeouts are no issue here. 51 | 52 | #include 53 | 54 | int main() 55 | { 56 | unsigned int exponent; 57 | std::cin >> exponent; 58 | 59 | // result 60 | unsigned int sum = 0; 61 | 62 | // there can't be a number with 8 digits (or more) which fulfils the condition for exponent=6 63 | // if all digits are 9s, then 64 | // 7 digits: 7 * 9^6 = 3720087 65 | // 8 digits: 8 * 9^6 = 4251528 66 | for (unsigned int i = 2; i <= 7*9*9*9*9*9*9; i++) 67 | { 68 | // sum of i's digits to the power of "exponent" 69 | unsigned int thisSum = 0; 70 | 71 | // split current number into its digit 72 | unsigned int reduce = i; 73 | while (reduce > 0) 74 | { 75 | // take the right-most digit 76 | unsigned int digit = reduce % 10; 77 | // and remove it 78 | reduce /= 10; 79 | 80 | // compute digit^exponent, could use pow() as well 81 | unsigned int power = 1; 82 | for (unsigned int j = 1; j <= exponent; j++) 83 | power *= digit; 84 | 85 | // add to thisSum 86 | thisSum += power; 87 | } 88 | 89 | // sum of digits^n equal to the original number ? 90 | if (thisSum == i) 91 | sum += i; 92 | } 93 | 94 | // and we're done 95 | std::cout << sum << std::endl; 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /euler-0034.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Digit factorials 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=34 7 | // http://euler.stephan-brumme.com/34/ 8 | // 9 | // # Problem 10 | // `145` is a curious number, as `1! + 4! + 5! = 1 + 24 + 120 = 145`. 11 | // 12 | // Find the sum of all numbers which are equal to the sum of the factorial of their digits. 13 | // 14 | // __Note:__ as `1! = 1` and `2! = 2` are not sums they are not included. 15 | // 16 | // # Solved by 17 | // Stephan Brumme 18 | // February 2017 19 | // 20 | // # Algorithm 21 | // This problem is very similar to problem 30. 22 | // 23 | // There is no 8-digit number which can be the sum of the factorials of its digits because `8 * 9! = 2903040` is a 7-digit number. 24 | // 25 | // I precomputed the factorials `0!` to `9!` instead of writing a short and simple __factorial__ function. 26 | // Each number is split into its digits (again I begin with the least-significant, "I chop them from the right side") 27 | // and then the factorial of these digits is looked up and added. 28 | // 29 | // Nothing spectacular - a very easy problem. 30 | // 31 | // # Hackerrank 32 | // The sums must be divisible by the number, not equal. 33 | 34 | #include 35 | 36 | int main() 37 | { 38 | // precompute factorials of all possible digits 0!..9! 39 | const unsigned int factorials[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 }; 40 | 41 | // no more than 7*9! = 2540160 for the original problem 42 | unsigned int limit; 43 | std::cin >> limit; 44 | 45 | // result (differs for Hackerrank modified problem !) 46 | unsigned int result = 0; 47 | 48 | for (unsigned int i = 10; i < limit; i++) 49 | { 50 | unsigned int sum = 0; 51 | 52 | // split i into its digits 53 | unsigned int x = i; 54 | while (x > 0) 55 | { 56 | // add factorial of the right-most digit 57 | sum += factorials[x % 10]; 58 | // remove that digit 59 | x /= 10; 60 | } 61 | 62 | #define ORIGINAL 63 | #ifdef ORIGINAL 64 | // equal ? 65 | if (sum == i) 66 | result += i; 67 | #else 68 | // divisible ? 69 | if (sum % i == 0) 70 | result += i; 71 | #endif 72 | } 73 | 74 | std::cout << result << std::endl; 75 | return 0; 76 | } 77 | -------------------------------------------------------------------------------- /euler-0035.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Circular primes 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=35 7 | // http://euler.stephan-brumme.com/35/ 8 | // 9 | // # Problem 10 | // The number, 197, is called a circular prime because all rotations of the digits: 197, 971, and 719, are themselves prime. 11 | // 12 | // There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, and 97. 13 | // 14 | // How many circular primes are there below one million? 15 | // 16 | // # Solved by 17 | // Stephan Brumme 18 | // February 2017 19 | // 20 | // # Algorithm 21 | // First, a a standard prime sieve finds all prime numbers up to our limit (1000000 by default) and keeps them in a ''std::set''. 22 | // 23 | // Then each prime ''x'' in ''std::set'' is rotated by one digit to the right: 24 | // 1. get the right-most digit: 25 | // ''auto digit = rotated % 10;'' 26 | // 2. move all digits by one digit to the right ("erasing" the right-most digit): 27 | // ''rotated /= 10;'' 28 | // 3. prepend the right-most digit: 29 | // '' rotated += digit * shift;'' 30 | // 4. check whether rotated is part of our ''std::set'', too 31 | // 5. if ''rotated'' is equal to our initial value ''x'' then we checked all rotations 32 | // 33 | // The only point of interest is ''shift'' which is a power of 10 such that `10^a = shift <= x <= 10^{a+1}`. 34 | // E.g., if `x = 3456` then `shift = 1000`. 35 | // 36 | // # Note 37 | // 38 | // There are a few options to speed up the code: 39 | // 1. All prime numbers are odd (except for 2): if ''x != 2'' and any digit is even then this prime can't be circular. 40 | // 2. We can simplify point 1 by noting that all single-digit primes are circular. 41 | // 42 | // # Hackerrank 43 | // We have to find the sum of all such prime numbers, not their count. 44 | 45 | #include 46 | #include 47 | 48 | int main() 49 | { 50 | // highest number (1000000 in original problem) 51 | unsigned int n; 52 | std::cin >> n; 53 | 54 | // precomputation: find all prime numbers up to n 55 | std::set primes; 56 | primes.insert(2); 57 | for (unsigned int i = 3; i <= n; i += 2) 58 | { 59 | bool isPrime = true; 60 | 61 | // test against all prime numbers we have so far (in ascending order) 62 | for (auto x : primes) 63 | { 64 | // divisible => not prime 65 | if (i % x == 0) 66 | { 67 | isPrime = false; 68 | break; 69 | } 70 | 71 | // prime is too large to be a divisor 72 | if (x*x > i) 73 | break; 74 | } 75 | 76 | // yes, we have a prime 77 | if (isPrime) 78 | primes.insert(i); 79 | } 80 | 81 | // now look at all primes 82 | unsigned int sum = 0; 83 | for (auto x : primes) 84 | { 85 | // move the right-most digit to the front of the number 86 | // we need to know the "position" of the front-most digit: 87 | // shift will be 1 for x = 1..9 88 | // shift will be 10 for x = 10..99 89 | // shift will be 100 for x = 100..999 and so on 90 | unsigned int shift = 1; 91 | while (x > shift * 10) 92 | shift *= 10; 93 | 94 | auto rotated = x; 95 | do 96 | { 97 | // take right-most digit 98 | auto digit = rotated % 10; 99 | // remove it 100 | rotated /= 10; 101 | // and prepend it 102 | rotated += digit * shift; 103 | 104 | // rotated number not prime ? 105 | if (primes.count(rotated) == 0) 106 | break; 107 | } while (rotated != x); // finished the circle ? (we have the initial number again) 108 | 109 | // all rotations succeeded ? 110 | #define ORIGINAL 111 | #ifdef ORIGINAL 112 | if (rotated == x) 113 | sum++; 114 | #else 115 | if (rotated == x) 116 | sum += x; 117 | #endif 118 | } 119 | 120 | std::cout << sum << std::endl; 121 | return 0; 122 | } 123 | -------------------------------------------------------------------------------- /euler-0036.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Double-base palindromes 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=36 7 | // http://euler.stephan-brumme.com/36/ 8 | // 9 | // # Problem 10 | // The decimal number, 585 = 10010010012 (binary), is palindromic in both bases. 11 | // Find the sum of all numbers, less than one million, which are palindromic in base 10 and base 2. 12 | // 13 | // (Please note that the palindromic number, in either base, may not include leading zeros.) 14 | // 15 | // # Solved by 16 | // Stephan Brumme 17 | // February 2017 18 | // 19 | // # Algorithm 20 | // My short function ''num2str'' converts a number ''x'' into a ''std::string'' with ''base''. 21 | // It's more or less the same code I used in previous problems when I wanted to extract right-most digit of a number. 22 | // Note that the result "grows" from right-to-left, that's why I always insert a single char at position 0. 23 | // 24 | // The function ''isPalindrome'' uses the STL function ''std::reverse'' to efficiently reverse a string in-place. 25 | // If it's identical to the original string, then we have a palindrome. 26 | // 27 | // The main loop checks number with base 10 first, because they are shorter than numbers with base 2 to 9. 28 | // In most cases we can abort earlier and save a little time. 29 | // 30 | // # Note 31 | // Of course you can speed up the whole process considerably: 32 | // 1. generate all numbers from ''1'' to ''y'' where ''y'' has half as many digits as ''x''. 33 | // 2. then convert to an ''std::string'' and append its reverse. 34 | // 3. convert that string to an integer ''x'' and test with ''isPalindrome(num2str(x, 2))'' whether ''x'' 's binary representation is a palindrome, too. 35 | // 36 | // This way you have to check 1000 instead of 1000000 numbers. 37 | // 38 | // I haven't benchmark it but my suspicion is that if ''num2str'' appends digits (instead of prepending) and reverses the string as a final step, 39 | // then we might see a speed-up as well. 40 | // 41 | // # Hackerrank 42 | // Base can be anything from 2 to 9. 43 | 44 | #include 45 | #include 46 | #include 47 | 48 | // base: decimal=10, binary=2 49 | std::string num2str(unsigned int x, unsigned int base) 50 | { 51 | std::string result; 52 | while (x > 0) 53 | { 54 | auto digit = x % base; 55 | x /= base; 56 | result.insert(0, 1, char(digit + '0')); 57 | } 58 | return result; 59 | } 60 | 61 | // true if string is a palindrome 62 | bool isPalindrome(const std::string& s) 63 | { 64 | auto other = s; 65 | std::reverse(other.begin(), other.end()); 66 | return other == s; 67 | } 68 | 69 | // I was quite surprised that the basic brute-force approach is sufficiently fast ... 70 | int main() 71 | { 72 | unsigned int limit, base; // limit = 1000000 and base = 2 73 | std::cin >> limit >> base; 74 | 75 | unsigned int sum = 0; 76 | for (unsigned int x = 1; x < limit; x++) 77 | if (isPalindrome(num2str(x, 10)) && // palindrome in base 10 ? 78 | isPalindrome(num2str(x, base))) // palindrome in base k ? 79 | // yes, double palindrome 80 | sum += x; 81 | 82 | std::cout << sum << std::endl; 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /euler-0043.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Sub-string divisibility 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=43 7 | // http://euler.stephan-brumme.com/43/ 8 | // 9 | // # Problem 10 | // The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9 in some order, 11 | // but it also has a rather interesting sub-string divisibility property. 12 | // 13 | // Let `d_1` be the 1st digit, `d_2` be the 2nd digit, and so on. In this way, we note the following: 14 | // 15 | // `d_2 d_3 d_4 = 406` is divisible by 2 16 | // `d_3 d_4 d_5 = 063` is divisible by 3 17 | // `d_4 d_5 d_6 = 635` is divisible by 5 18 | // `d_5 d_6 d_7 = 357` is divisible by 7 19 | // `d_6 d_7 d_8 = 572` is divisible by 11 20 | // `d_7 d_8 d_9 = 728` is divisible by 13 21 | // `d_8 d_9 d_10 = 289` is divisible by 17 22 | // 23 | // Find the sum of all 0 to 9 pandigital numbers with this property. 24 | // 25 | // # Solved by 26 | // Stephan Brumme 27 | // February 2017 28 | // 29 | // # Algorithm 30 | // Once more, ''std::next_permutation'' turns out to be a rather handy feature: 31 | // I generate all permutations of ''pan = "0123456789"'' and check all its substrings with length 3 for divisibility with the first prime numbers. 32 | // 33 | // ''str2num'' converts an ASCII string to a number, ignoring leading zeros: ''str2num("012") = 12'' 34 | // 35 | // We need only the first 7 prime numbers - that's why I opted against a full prime sieve and just declared a precomputed array ''primes''. 36 | // 37 | // # Note 38 | // Ten digits can exceed 32 bits, therefore you'll find ''unsigned long long'' instead of ''unsigned int'' in a few places. 39 | // 40 | // There are many optimization possible: when applying the rules of divisibility by 3, 5, ... then 41 | // we could easily exclude the majority of permutations. Nevertheless, the non-optimized code runs fast enough. 42 | // 43 | // # Hackerrank 44 | // The number of digits can vary. All I do is adjusting ''pan'': anything else remains the same. 45 | // Hackerrank accepts pandigital numbers that start with a zero. 46 | 47 | #include 48 | #include 49 | #include 50 | 51 | // convert a string to a number 52 | unsigned long long str2num(const std::string& x) 53 | { 54 | // process string from left to right 55 | unsigned long long result = 0; 56 | for (auto c : x) 57 | { 58 | // shift digits 59 | result *= 10; 60 | // add new digit on the right-hand side 61 | result += c - '0'; // was ASCII 62 | } 63 | return result; 64 | } 65 | 66 | int main() 67 | { 68 | // available digits 69 | std::string pan = "0123456789"; // unlike other problems, zero is allowed this time 70 | 71 | // remove a few digits if test case requires this 72 | unsigned int maxDigit; 73 | std::cin >> maxDigit; 74 | pan.erase(maxDigit + 1); 75 | 76 | // all divisors 77 | const unsigned int primes[] = { 2,3,5,7,11,13,17 }; 78 | 79 | // result 80 | unsigned long long sum = 0; 81 | 82 | // look at all permutations 83 | do 84 | { 85 | // let's assume it's a great number ;-) 86 | bool ok = true; 87 | 88 | // check each 3-digit substring for divisibility 89 | for (unsigned int i = 0; i + 2 < maxDigit; i++) 90 | { 91 | // check pan[1..3] against primes[0], 92 | // check pan[2..4] against primes[1], 93 | // check pan[3..5] against primes[2] ... 94 | std::string check = pan.substr(i + 1, 3); 95 | if (str2num(check) % primes[i] != 0) 96 | { 97 | // nope ... 98 | ok = false; 99 | break; 100 | } 101 | } 102 | 103 | // passed all tests, it's great indeed ! 104 | if (ok) 105 | sum += str2num(pan); 106 | } while (std::next_permutation(pan.begin(), pan.end())); 107 | 108 | std::cout << sum << std::endl; 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /euler-0045.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Triangular, pentagonal, and hexagonal 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=45 7 | // http://euler.stephan-brumme.com/45/ 8 | // 9 | // # Problem 10 | // Triangle, pentagonal, and hexagonal numbers are generated by the following formulae: 11 | // Triangle `T_n=n(n+1)/2` 12 | // ==> 1, 3, 6, 10, 15, ... 13 | // Pentagonal `P_n=n(3n-1)/2` 14 | // ==> 1, 5, 12, 22, 35, ... 15 | // Hexagonal `H_n=n(2n-1)` 16 | // ==> 1, 6, 15, 28, 45, ... 17 | // 18 | // It can be verified that `T_285 = P_165 = H_143 = 40755`. 19 | // Find the next triangle number that is also pentagonal and hexagonal. 20 | // 21 | // # Solved by 22 | // Stephan Brumme 23 | // February 2017 24 | // 25 | // # Algorithm 26 | // In Problem 42 and Problem 44 I already had to check a number whether it is a triangular or a pentagonal number. 27 | // 28 | // My code generates all hexagonal numbers (starting with `H_144`). And stop as soon as I find a hexagonal number that is triangular and pentagonal, too. 29 | // 30 | // By the way: every hexagonal number is triangular, too: 31 | // `H_n=T_{2n-1}` 32 | // 33 | // # Hackerrank 34 | // The problem was heavily modified by Hackerrank: 35 | // the program has to find all numbers, up to an input value, that are 36 | // - triangular and pentagonal or 37 | // - pentagonal and hexagonal 38 | 39 | #include 40 | #include 41 | 42 | // note: isTriangular and isPentagonal based on Euler problems 42 and 44 43 | 44 | bool isTriangular(unsigned long long x) 45 | { 46 | unsigned long long n = sqrt(2*x); 47 | 48 | // if n is actually the right answer then t(n) = x 49 | unsigned long long check = n * (n + 1) / 2; 50 | return (x == check); 51 | } 52 | 53 | bool isPentagonal(unsigned long long x) 54 | { 55 | unsigned long long n = (1 + sqrt(24*x + 1)) / 6; 56 | 57 | // if x was indeed a pentagonal number then our assumption P(n) = x must be true 58 | auto p_n = n * (3 * n - 1) / 2; 59 | return p_n == x; 60 | } 61 | 62 | int main() 63 | { 64 | //#define ORIGINAL 65 | #ifdef ORIGINAL 66 | // 143 is the first number which is triangular, pentagonal and hexagonal 67 | for (unsigned int i = 144; ; i++) 68 | { 69 | unsigned int hexagonal = i * (2*i - 1); 70 | if (isPentagonal(hexagonal)) 71 | { 72 | // found it ! 73 | std::cout << hexagonal << std::endl; 74 | return 0; 75 | } 76 | } 77 | 78 | #else 79 | 80 | // hexagonal numbers grow the fastest, triangular the slowest 81 | unsigned long long limit; 82 | unsigned int a, b; 83 | std::cin >> limit >> a >> b; 84 | 85 | // triangular and pentagonal at the same time 86 | if (a == 3 && b == 5) 87 | { 88 | // let's generate the sequence of all pentagonal numbers, check if triangular, too 89 | for (unsigned long long i = 1; ; i++) 90 | { 91 | auto pentagonal = i * (3*i - 1) / 2; 92 | if (pentagonal >= limit) 93 | break; 94 | 95 | if (isTriangular(pentagonal)) 96 | std::cout << pentagonal << std::endl; 97 | } 98 | } 99 | // same idea for pentagonal and hexagonal numbers 100 | if (a == 5 && b == 6) 101 | { 102 | // let's generate the sequence of all hexagonal numbers, check if pentagonal, too 103 | for (unsigned long long i = 1; ; i++) 104 | { 105 | auto hexagonal = i * (2*i - 1); 106 | if (hexagonal >= limit) 107 | break; 108 | 109 | if (isPentagonal(hexagonal)) 110 | std::cout << hexagonal << std::endl; 111 | } 112 | } 113 | 114 | #endif 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /euler-0046.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Goldbach's other conjecture 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=46 7 | // http://euler.stephan-brumme.com/46/ 8 | // 9 | // # Problem 10 | // It was proposed by Christian Goldbach that every odd composite number can be written as the sum of a prime and twice a square. 11 | // 12 | // ` 9 = 7 + 2 * 1^2` 13 | // `15 = 7 + 2 * 2^2` 14 | // `21 = 3 + 2 * 3^2` 15 | // `25 = 7 + 2 * 3^2` 16 | // `27 = 19 + 2 * 2^2` 17 | // `33 = 31 + 2 * 1^2` 18 | // 19 | // It turns out that the conjecture was false. 20 | // What is the smallest odd composite that cannot be written as the sum of a prime and twice a square? 21 | // 22 | // # Solved by 23 | // Stephan Brumme 24 | // February 2017 25 | // 26 | // # Algorithm 27 | // A standard prime sieve quickly finds all primes up to 500000. 28 | // For all odd numbers `i` my program generate all squares `j^2 < i`. 29 | // If no `j` exists such that `i - j^2` is prime then Goldbach's other conjecture is refuted. 30 | // 31 | // # Hackerrank 32 | // Again, the Hackerrank problem is significantly different from the original Project Euler problem: 33 | // we have to find all ways to represent it as a sum of a prime number and twice a square. 34 | // 35 | // My program generates all squares `j^2 < i` and count how often `i - j^2` is prime. 36 | 37 | #include 38 | #include 39 | 40 | int main() 41 | { 42 | const unsigned int MaxPrime = 500000; 43 | // find all primes up to 500000 44 | std::set primes; 45 | primes.insert(2); 46 | for (unsigned int i = 3; i < MaxPrime; i += 2) 47 | { 48 | bool isPrime = true; 49 | // test against all prime numbers we have so far (in ascending order) 50 | for (auto p : primes) 51 | { 52 | // next prime is too large to be a divisor 53 | if (p*p > i) 54 | break; 55 | 56 | // divisible => not prime 57 | if (i % p == 0) 58 | { 59 | isPrime = false; 60 | break; 61 | } 62 | } 63 | 64 | // yes, we have a prime number 65 | if (isPrime) 66 | primes.insert(i); 67 | } 68 | 69 | //#define ORIGINAL 70 | #ifdef ORIGINAL 71 | // start at 9 (smallest odd number which is not prime) 72 | for (unsigned int i = 9; i <= MaxPrime; i += 2) 73 | { 74 | // only composite numbers 75 | if (primes.count(i) != 0) 76 | continue; 77 | 78 | bool refuteConjecture = true; 79 | // try all squares 80 | for (unsigned int j = 1; 2*j*j < i; j++) 81 | { 82 | auto check = i - 2*j*j; 83 | // found a combination, conjecture is still valid 84 | if (primes.count(check) != 0) 85 | { 86 | refuteConjecture = false; 87 | break; 88 | } 89 | } 90 | 91 | // conjecture refuted ! 92 | if (refuteConjecture) 93 | { 94 | std::cout << i << std::endl; 95 | break; 96 | } 97 | } 98 | 99 | #else 100 | 101 | unsigned int tests; 102 | std::cin >> tests; 103 | while (tests--) 104 | { 105 | unsigned int i; 106 | std::cin >> i; 107 | 108 | // try all squares 109 | unsigned int solutions = 0; 110 | for (unsigned int j = 1; 2*j*j < i; j++) 111 | { 112 | // check whether i - j^2 is prime 113 | unsigned int check = i - 2*j*j; 114 | // yes, found another combination 115 | if (primes.count(check) != 0) 116 | solutions++; 117 | } 118 | 119 | std::cout << solutions << std::endl; 120 | } 121 | #endif 122 | 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /euler-0047.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Distinct primes factors 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=47 7 | // http://euler.stephan-brumme.com/47/ 8 | // 9 | // # Problem 10 | // The first two consecutive numbers to have two distinct prime factors are: 11 | // `14 = 2 * 7` 12 | // `15 = 3 * 5` 13 | // 14 | // The first three consecutive numbers to have three distinct prime factors are: 15 | // `644 = 2^2 * 7 * 23` 16 | // `645 = 3 * 5 * 43` 17 | // `646 = 2 * 17 * 19` 18 | // 19 | // Find the first four consecutive integers to have four distinct prime factors each. 20 | // What is the first of these numbers? 21 | // 22 | // # Solved by 23 | // Stephan Brumme 24 | // February 2017 25 | // 26 | // # Algorithm 27 | // Most of my prime sieves are based on trial division - this time the Sieve of Eratosthenes is a perfect fit. 28 | // But instead of "crossing off" composite numbers, I increment a counter: 29 | // - it's 1 if the number ''i'' itself is the only prime factor (well, then ''i'' is a prime number !) 30 | // - it's greater than 1 for composite numbers 31 | // 32 | // A counter ''currentRun'' is incremented by one as long as the current number has the desired number of distinct prime factors. 33 | // If the number of prime factors deviated, then ''currentRun'' is reset to zero. 34 | // 35 | // If ''currentRun >= consecutive'' then I print the position of the first number, which was ''i - consecutive + 1''. 36 | 37 | #include 38 | #include 39 | 40 | int main() 41 | { 42 | unsigned int maxNumber = 500000; 43 | unsigned int consecutive = 4; 44 | std::cin >> maxNumber >> consecutive; 45 | 46 | // a group of consecutive numbers might extend beyond maxNumber 47 | // therefore adjust our search range accordingly 48 | maxNumber += consecutive - 1; 49 | 50 | // count prime factors of each number (1 is not considered a prime factor) 51 | std::vector primeFactors(maxNumber + 1, 0); 52 | 53 | // modified Sieve of Eratosthenes 54 | for (unsigned int i = 2; i <= maxNumber; i++) 55 | // is i a prime ? 56 | if (primeFactors[i] == 0) 57 | // all multiples of i have i as a prime factor 58 | for (unsigned int j = i; j <= maxNumber; j += i) 59 | primeFactors[j]++; 60 | 61 | // iterate over all numbers 62 | unsigned int currentRun = 0; 63 | for (unsigned int i = 2; i <= maxNumber; i++) 64 | { 65 | // match ? 66 | if (primeFactors[i] == consecutive) 67 | { 68 | currentRun++; 69 | 70 | // enough such numbers in a row ? print the first 71 | if (currentRun >= consecutive) 72 | std::cout << (i - consecutive + 1) << std::endl; 73 | } 74 | else 75 | { 76 | // reset counter 77 | currentRun = 0; 78 | } 79 | } 80 | 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /euler-0052.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Permuted multiples 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=52 7 | // http://euler.stephan-brumme.com/52/ 8 | // 9 | // # Problem 10 | // It can be seen that the number, 125874, and its double, 251748, contain exactly the same digits, but in a different order. 11 | // Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, contain the same digits. 12 | // 13 | // # Solved by 14 | // Stephan Brumme 15 | // February 2017 16 | // 17 | // # Algorithm 18 | // My function ''fingerprint'' counts how often each digit occurs and produces an integer (which may have up to 10 digits). 19 | // The n-th decimal digit of the result represents how often the digit n occurs in the input, e.g. 20 | // ''fingerprint(454430) = 131001'' 21 | // because ''5'' appears once, ''4'' three times, ''3'' once, no ''2'', no ''1'' and a single zero. 22 | // ''fingerprint'' has the nice property that two number with the same fingerprint are a permutation of each other 23 | // (phrased in the words of the problem statement: "contain the same digits"). 24 | // 25 | // __Note:__ my fingerprint technique allows only up 9 identical digits which is okay because ''x'' has at most seven digits. 26 | // 27 | // I compute the fingerprint of each number ''i'', beginning with 1, and multiply it by 2, 3, 4, ... 28 | // If the product still has the same fingerprint, then it is a permutation. 29 | // 30 | // # Note 31 | // The is plenty of room for optimization. For example, if ''maxMultiple >= 5'' then the first digit of ''i'' must be a ''1''. 32 | // 33 | // # Hackerrank 34 | // The number of multiples can be adjusted from 2 to 6 (the latter being the default value for the original problem). 35 | 36 | #include 37 | 38 | // I generate a "fingerprint" for each number: 39 | // e.g. a fingerprint of 40231 means that the parameter had 40 | // 1 zero 41 | // 3 ones 42 | // 2 threes 43 | // no fours 44 | // 4 fives 45 | // and no sixes, sevens, ... 46 | unsigned long long fingerprint(unsigned int x) 47 | { 48 | unsigned long long result = 0; 49 | 50 | while (x > 0) 51 | { 52 | // extract right-most digit 53 | auto digit = x % 10; 54 | x /= 10; 55 | 56 | // add 10^digit 57 | unsigned long long pos = 1; 58 | for (unsigned int i = 1; i <= digit; i++) 59 | pos *= 10; 60 | result += pos; 61 | } 62 | 63 | return result; 64 | } 65 | 66 | int main() 67 | { 68 | // the result can be found with 1000000 6 69 | unsigned int maxNumber = 1000000; 70 | unsigned int maxMultiple = 6;; 71 | std::cin >> maxNumber >> maxMultiple; 72 | 73 | // look at all numbers 74 | for (unsigned int i = 1; i <= maxNumber; i++) 75 | { 76 | // initial fingerprint 77 | auto id = fingerprint(i); 78 | 79 | bool found = true; 80 | for (unsigned int multiple = 2; multiple <= maxMultiple; multiple++) 81 | // mismatch ? => abort 82 | if (id != fingerprint(i * multiple)) 83 | { 84 | found = false; 85 | break; 86 | } 87 | 88 | // print result 89 | if (found) 90 | { 91 | //#define ORIGINAL 92 | #ifdef ORIGINAL 93 | std::cout << i << std::endl; 94 | return 0; 95 | #endif 96 | 97 | for (unsigned int multiple = 1; multiple <= maxMultiple; multiple++) 98 | std::cout << (i * multiple) << " "; 99 | std::cout << std::endl; 100 | } 101 | } 102 | 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /euler-0053.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Combinatoric selections 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=53 7 | // http://euler.stephan-brumme.com/53/ 8 | // 9 | // # Problem 10 | // There are exactly ten ways of selecting three from five, 12345: 11 | // 12 | // 123, 124, 125, 134, 135, 145, 234, 235, 245, and 345 13 | // 14 | // In combinatorics, we use the notation, `^5C_3 = 10`. 15 | // 16 | // In general, 17 | // `^nC_r = dfrac{n!}{r! * (n-r)!}` where `r <= n`, `n! = n * (n-1) * ... * 3 * 2 * 1`, and `0! = 1`. 18 | // 19 | // It is not until `n = 23`, that a value exceeds one-million: `^{23}C_10 = 1144066`. 20 | // 21 | // How many, not necessarily distinct, values of `^nC_r`, for `1 <= n <= 100`, are greater than one-million? 22 | // 23 | // # Solved by 24 | // Stephan Brumme 25 | // February 2017 26 | // 27 | // # Algorithm 28 | // The formulas based on factorials (those provided in the problem statement) allow a direct computation of `^nC_r`. 29 | // However, you might get very big numbers in the numerator and/or denominator - they easily exceed the range of a 32 or 64 bit integer. 30 | // 31 | // There is another formula - the recursive definition: 32 | // - `^nC_0 = {^nC_n} = 1` and 33 | // - `^nC_k = {^{n-1}C_{k-1}} + {^{n-1}C_k}` 34 | // 35 | // As soon as any `^nC_k` exceeds ''maxNumber'', I set it to ''maxNumber + 1''. This value still fits into an 64 bit integer (even ''2*(maxNumber+1)'' is no problem). 36 | // At the same time, ''bigNumbers'' is incremented. 37 | // 38 | // I am allowed to replace `^nC_k` by ''maxNumber + 1'' because the true value of `^nC_k` doesn't really matter - all we want to know is whether `^nC_k > maxNumber` - or not. 39 | // 40 | // When all values are processed, ''bigNumbers'' is displayed. 41 | // 42 | // # Note 43 | // The program could use less memory: instead of storing all values of ''combinations[n][k]'' it is sufficient to keep only 44 | // ''combinations[n-1][]'' and ''combinations[n][]'', thus reducing the memory requirements from `maxN^2` to `2*maxN`. 45 | 46 | #include 47 | #include 48 | 49 | int main() 50 | { 51 | // maximum index n and/or k 52 | unsigned int maxN = 100; 53 | // what is considered "big" ? 54 | unsigned long long maxNumber = 1000000; 55 | std::cin >> maxN >> maxNumber; 56 | 57 | // this will be the displayed result 58 | unsigned int bigNumbers = 0; 59 | 60 | // setup a 2D array to hold all values 61 | std::vector> combinations(maxN + 1); 62 | 63 | // C(n,0) = C(n,n) = 1 64 | for (unsigned int n = 0; n <= maxN; n++) 65 | { 66 | combinations[n].resize(n + 1, 0); 67 | combinations[n][0] = combinations[n][n] = 1; 68 | } 69 | 70 | // recursive definition: 71 | // C(n,k) = C(n-1, k-1) + C(n-1, k) 72 | for (unsigned int n = 1; n <= maxN; n++) 73 | for (unsigned int k = 1; k < n; k++) 74 | { 75 | auto sum = combinations[n - 1][k - 1] + combinations[n - 1][k]; 76 | // clamp numbers to avoid exceeding 64 bits 77 | if (sum > maxNumber) 78 | { 79 | sum = maxNumber + 1; 80 | // we found one more big number 81 | bigNumbers++; 82 | } 83 | 84 | // store result 85 | combinations[n][k] = sum; 86 | } 87 | 88 | std::cout << bigNumbers << std::endl; 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /euler-0056.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Powerful digit sum 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=56 7 | // http://euler.stephan-brumme.com/56/ 8 | // 9 | // # Problem 10 | // A googol (`10^100`) is a massive number: one followed by one-hundred zeros; `100^100` is almost unimaginably large: one followed by two-hundred zeros. 11 | // Despite their size, the sum of the digits in each number is only 1. 12 | // 13 | // Considering natural numbers of the form, ab, where a, b < 100, what is the maximum digital sum? 14 | // 15 | // # Solved by 16 | // Stephan Brumme 17 | // February 2017 18 | // 19 | // # Algorithm 20 | // I wrote a small class ''BigNum'' that handles arbitrarily large integers (only positive, no sign). 21 | // It supports multiplication based on the simple algorithm that you'd use with pen and paper, too. 22 | // 23 | // My inner loop has a variable called ''power'' which represents `base^{exponent}`. Then `base^{exponent+1} = base^{exponent} * base`. 24 | // The digit sum iterates over all digits and keeps track of the largest sum (''maxSum''). 25 | 26 | #include 27 | #include 28 | 29 | // store single digits with lowest digits first 30 | // e.g. 1024 is stored as { 4,2,0,1 } 31 | // only non-negative numbers supported 32 | struct BigNum : public std::vector 33 | { 34 | // must be 10 for this problem: a single "cell" store one digit 0 <= digit < 10 35 | static const unsigned int MaxDigit = 10; 36 | 37 | // store a non-negative number 38 | BigNum(unsigned long long x = 0) 39 | { 40 | // actually the constructor is always called with x = 1, but I keep my default implementation 41 | do 42 | { 43 | push_back(x % MaxDigit); 44 | x /= MaxDigit; 45 | } while (x > 0); 46 | } 47 | 48 | // multiply a big number by an integer 49 | BigNum operator*(unsigned int factor) const 50 | { 51 | unsigned long long carry = 0; 52 | auto result = *this; 53 | // multiply each block by the number, take care of temporary overflows (carry) 54 | for (auto& i : result) 55 | { 56 | carry += i * (unsigned long long)factor; 57 | i = carry % MaxDigit; 58 | carry /= MaxDigit; 59 | } 60 | // store remaining carry in new digits 61 | while (carry > 0) 62 | { 63 | result.push_back(carry % MaxDigit); 64 | carry /= MaxDigit; 65 | } 66 | 67 | return result; 68 | } 69 | }; 70 | 71 | int main() 72 | { 73 | // maximum base/exponent (100 for Googol) 74 | unsigned int maximum = 100; 75 | std::cin >> maximum; 76 | 77 | // look at all i^j 78 | unsigned int maxSum = 1; 79 | for (unsigned int base = 1; base <= maximum; base++) 80 | { 81 | // incrementally compute base^exponent 82 | BigNum power = 1; 83 | for (unsigned int exponent = 1; exponent <= maximum; exponent++) 84 | { 85 | // add all digits 86 | unsigned int sum = 0; 87 | for (auto digit : power) 88 | sum += digit; 89 | 90 | // new world record ? ;-) 91 | if (maxSum < sum) 92 | maxSum = sum; 93 | 94 | // same base, next exponent: 95 | // base^(exponent + 1) = (base^exponent) * base 96 | power = power * base; 97 | } 98 | } 99 | 100 | std::cout << maxSum << std::endl; 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /euler-0062.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Cubic permutations 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=62 7 | // http://euler.stephan-brumme.com/62/ 8 | // 9 | // # Problem 10 | // The cube, 41063625 (`345^3`), can be permuted to produce two other cubes: 56623104 (`384^3`) and 66430125 (`405^3`). 11 | // In fact, 41063625 is the smallest cube which has exactly three permutations of its digits which are also cube. 12 | // 13 | // Find the smallest cube for which exactly five permutations of its digits are cube. 14 | // 15 | // # Solved by 16 | // Stephan Brumme 17 | // March 2017 18 | // 19 | // # Algorithm 20 | // A function ''fingerprint'' was already used in problem 49 and problem 52: if ''fingerprint(a) == fingerprint(b)'' then ''a'' is a permutation of ''b''. 21 | // 22 | // Step 1 of my program computes all cubes from `1^3` to `maxCube^3`and stores them indexed by their fingerprint (see ''matches''). 23 | // 24 | // Step 2 goes through all fingerprints with the specified number of permutations and transfers each fingerprint's first cube (the "smallest") to an ''std::set'' called ''smallest''. 25 | // 26 | // Finally, ''smallest^3'' is printed - using the fact that each ''std::set'' is automatically sorted (needed for the Hackerrank version of the problem). 27 | // 28 | // # Hackerrank 29 | // The modified problem requires all permutations to be below `maxCube^3`. 30 | // When running the problem with the official solution (parameter ''xyz 5'' where ''xyz'' is the solution) then it will fail to find the correct solution. 31 | // 32 | // The reason is that all but the initial permutations of `maxCube^3` are bigger than `maxCube^3`. 33 | // Therefore the solution is only found if all cubes are processed which produce the solution __and__ all bigger cubes that have still the same number of digits. 34 | // To be safe, the parameter should be `solution * {^3}sqrt{10} approx solution * 2.16`. 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | // count how often each digit occurs, 42 | // store zero at lowest position, then ones, etc. 43 | // e.g. 5063 means 3 zeros, 6 ones, no twos, 5 threes and nothing else 44 | // note: can't handle input values with 2^6 or more identical digits 45 | unsigned long long fingerprint(unsigned long long x) 46 | { 47 | unsigned long long result = 0; 48 | while (x > 0) 49 | { 50 | // extract lowest digit 51 | auto digit = x % 10; 52 | x /= 10; 53 | 54 | // subdivide 64 bit integer into 10 "digit counters", each 6 bits wide 55 | // => each digit may occur up to 2^6=64 times, more than enough ... 56 | const auto BitsPerDigit = 6; 57 | result += 1ULL << (BitsPerDigit * digit); 58 | } 59 | return result; 60 | } 61 | 62 | int main() 63 | { 64 | unsigned int maxCube = 10000; 65 | unsigned int numPermutations = 5; 66 | std::cin >> maxCube >> numPermutations; 67 | 68 | // [fingerprint] => [list of numbers, where number^3 produced that fingerprint] 69 | std::map> matches; 70 | for (unsigned int i = 1; i < maxCube; i++) 71 | { 72 | // find fingerprint 73 | auto cube = (unsigned long long)i * i * i; 74 | // add current number to the fingerprint's list 75 | matches[fingerprint(cube)].push_back(i); 76 | } 77 | 78 | // extract all smallest cube, std::set is sorting them 79 | std::set smallest; 80 | for (auto m : matches) 81 | // right number of permutations ? 82 | if (m.second.size() == numPermutations) 83 | smallest.insert(m.second.front()); 84 | 85 | // print in ascending order 86 | for (auto s : smallest) 87 | std::cout << (s*s*s) << std::endl; 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /euler-0063.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Powerful digit counts 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=63 7 | // http://euler.stephan-brumme.com/63/ 8 | // 9 | // # Problem 10 | // The 5-digit number, `16807=7^5`, is also a fifth power. Similarly, the 9-digit number, `134217728=8^9`, is a ninth power. 11 | // 12 | // How many n-digit positive integers exist which are also an nth power? 13 | // 14 | // # Solved by 15 | // Stephan Brumme 16 | // February 2017 17 | // 18 | // # Algorithm 19 | // ''check(n)'' finds all such powers with ''n'' digits: 20 | // - first it generates the smallest n-digit number ''from'' and the largest n-digit number ''to'' 21 | // - e.g. for ''n=5'' we have ''from=10000'' and ''to=99999'' 22 | // - then all numbers ''1^n'' to ''9^n'' are computed, if they are between ''from'' and ''to'' we have a match 23 | // 24 | // While experimenting I saw no number with more than 21 digits to fulfilled the problem's conditions. 25 | // 26 | // A minor headache was that 21 digits don't fit into C++ ''unsigned long long'' anymore. 27 | // Therefore I switched to ''double'' which has a few rounding issues but they don't affect the original problem. 28 | // 29 | // # Hackerrank 30 | // Hackerrank wants you to print all powers with a certain number of digits - instead of finding the number of all such powers. 31 | // However, the rounding issues of ''double'' now come into play and the right-most digits are a bit off for large ''n''. 32 | // 33 | // Fortunately, Hackerrank wants us only to find the powers with at most 19 digits ... and a 64 bit ''unsigned long long'' is sufficient for this task. 34 | // That's why you find the ''#ifdef'' construct where the type of ''Number'' is defined. 35 | // 36 | // # Alternative 37 | // It's easy to determine the number of digits using ''log10''. 38 | // And as mentioned in the code, ''pow(a,b)'' returns `a^b`. 39 | // Both functions are available in the C++ standard library. 40 | 41 | #include 42 | 43 | //#define ORIGINAL 44 | 45 | // find all numbers where x^digits has digits digits (I'm loving that comment ...) 46 | unsigned int check(unsigned int digits) 47 | { 48 | // numbe rof matches 49 | unsigned int count = 0; 50 | 51 | // unsigned long long isn't sufficient for the highest digits 52 | // a double has some rounding issues but they don't affect to result 53 | #ifdef ORIGINAL 54 | typedef double Number; 55 | #else 56 | typedef unsigned long long Number; 57 | #endif 58 | 59 | // range of valid numbers 60 | // from = 10^(digits-1) 61 | // to = 10^digits - 1 62 | Number to = 1; 63 | for (unsigned int i = 1; i <= digits; i++) 64 | to *= 10; 65 | Number from = to / 10; 66 | to--; 67 | 68 | // try all single-digit base numbers 69 | for (unsigned int base = 1; base <= 9; base++) 70 | { 71 | // compute power = base ^ digits 72 | Number power = base; 73 | for (unsigned int i = 1; i < digits && power <= to; i++) 74 | power *= base; 75 | // could use C++'s pow(), too 76 | 77 | // right number of digits ? 78 | if (power >= from && power <= to) 79 | { 80 | count++; 81 | #ifndef ORIGINAL 82 | std::cout << std::fixed << power << std::endl; 83 | #endif 84 | } 85 | } 86 | 87 | return count; 88 | } 89 | 90 | int main() 91 | { 92 | #ifdef ORIGINAL 93 | // check all digits 94 | unsigned int count = 0; 95 | for (unsigned int digits = 1; digits <= 21; digits++) // I observed no results with more than 21 digits 96 | count += check(digits); 97 | std::cout << count << std::endl; 98 | 99 | #else 100 | 101 | // check only certain digits 102 | unsigned int digits = 9; 103 | std::cin >> digits; 104 | check(digits); 105 | #endif 106 | 107 | return 0; 108 | } 109 | -------------------------------------------------------------------------------- /euler-0069.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Totient maximum 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=69 7 | // http://euler.stephan-brumme.com/69/ 8 | // 9 | // # Problem 10 | // Euler's Totient function, `phi(n)` [sometimes called the phi function], is used to determine the number of numbers less than `n` which are relatively prime to `n`. 11 | // For example, as 1, 2, 4, 5, 7, and 8, are all less than nine and relatively prime to nine, `phi(9)=6`. 12 | // 13 | // || 2 || 8 || 4 || 4 || 14 | // || `n` || Relatively Prime || `phi(n)` || `n/phi(n)` || 15 | // ||-----||-------------------||----------||------------|| 16 | // || 2 || 1 || 1 || 2 || 17 | // || 3 || 1,2 || 2 || 1.5 || 18 | // || 4 || 1,3 || 2 || 2 || 19 | // || 5 || 1,2,3,4 || 4 || 1.25 || 20 | // || 6 || 1,5 || 2 || 3 || 21 | // || 7 || 1,2,3,4,5,6 || 6 || 1.1666... || 22 | // || 8 || 1,3,5,7 || 4 || 2 || 23 | // || 9 || 1,2,4,5,7,8 || 6 || 1.5 || 24 | // || 10 || 1,3,7,9 || 4 || 2.5 || 25 | // 26 | // It can be seen that `n=6` produces a maximum `n/phi(n)` for `n <= 10`. 27 | // 28 | // Find the value of `n <= 1000000` for which `n/phi(n)` is a maximum. 29 | // 30 | // # Solved by 31 | // Stephan Brumme 32 | // March 2017 33 | // 34 | // # Algorithm 35 | // I have no formal proof yet (it's too late - time to go to bed !): 36 | // in my first brute-force attempt I observed that the "best number" is the product of all primes 37 | // `best = 2 * 3 * 5 * 7 * 11 * 13 * ...` where `best < 1000000`. 38 | // 39 | // Simple tests showed that all primes from 2 to 57 are sufficient. 40 | // 41 | // # Hackerrank 42 | // The test ''best * nextPrime >= limit'' might overflow. 43 | // The same result can be achieved this way: 44 | // `best * nextPrime >= limit` 45 | // 46 | // `best >= dfrac{limit}{nextPrime}` 47 | // 48 | // All variables are integers and thus rounding comes into play. 49 | // The correct formula is: 50 | // `best >= dfrac{limit}{nextPrime} + dfrac{nextPrime - 1}{nextPrime}` 51 | // 52 | // `best >= dfrac{limit + nextPrime - 1}{nextPrime}` 53 | 54 | #include 55 | 56 | int main() 57 | { 58 | // enough primes for this problem 59 | const unsigned int primes[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 57 }; 60 | 61 | unsigned int tests; 62 | std::cin >> tests; 63 | while (tests--) 64 | { 65 | unsigned long long limit; 66 | std::cin >> limit; 67 | 68 | // multiply until we hit our limit 69 | unsigned long long bestPos = 1; 70 | for (auto p : primes) 71 | { 72 | // continue until bestPos reaches or exceeds our input value 73 | //__int128 next = bestPos * p; 74 | //if (next >= limit) 75 | // break; 76 | // same code as before but more portable: 77 | if (bestPos >= (limit + p - 1) / p) 78 | break; 79 | 80 | bestPos *= p; 81 | } 82 | 83 | std::cout << bestPos << std::endl; 84 | } 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /euler-0072.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Counting fractions 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=72 7 | // http://euler.stephan-brumme.com/72/ 8 | // 9 | // # Problem 10 | // Consider the fraction, `dfrac{n}{d}`, where `n` and `d` are positive integers. If `n 36 | #include 37 | 38 | int main() 39 | { 40 | // 1. initialize phi(x) = x for all numbers 41 | unsigned int limit = 1000000; 42 | std::vector phi(limit + 1); // vectors are zero-based 43 | for (size_t i = 0; i < phi.size(); i++) 44 | phi[i] = i; 45 | 46 | // 2. for all multiples of a prime: 47 | // phi_new(k*prime) = phi_old(k*prime) * (1 - 1/prime) 48 | // = phi_old(k*prime) - phi_old(k*prime) / prime 49 | for (unsigned int i = 2; i <= limit; i++) 50 | { 51 | // prime number ? (because not modified yet by other primes) 52 | if (phi[i] == i) 53 | // adjust all multiples 54 | for (unsigned int k = 1; k * i <= limit; k++) 55 | phi[k * i] -= phi[k * i] / i; 56 | } 57 | 58 | // note: since we are only interested in 0 < fractions < 1 59 | // we have to exclude phi(1) (which would yield 1/1 = 1) 60 | // and start at phi(2) 61 | 62 | std::vector sums(phi.size(), 0); 63 | // 3. compute all sums phi(2) + phi(3) + ... + phi(i) 64 | for (unsigned int i = 2; i <= limit; i++) 65 | sums[i] = sums[i - 1] + phi[i]; 66 | 67 | unsigned int tests = 1; 68 | std::cin >> tests; 69 | while (tests--) 70 | { 71 | std::cin >> limit; 72 | std::cout << sums[limit] << std::endl; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /euler-0076.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Counting summations 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=76 7 | // http://euler.stephan-brumme.com/76/ 8 | // 9 | // # Problem 10 | // It is possible to write five as a sum in exactly six different ways: 11 | // 12 | // 4 + 1 13 | // 3 + 2 14 | // 3 + 1 + 1 15 | // 2 + 2 + 1 16 | // 2 + 1 + 1 + 1 17 | // 1 + 1 + 1 + 1 + 1 18 | // 19 | // How many different ways can one hundred be written as a sum of at least two positive integers? 20 | // 21 | // # Solved by 22 | // Stephan Brumme 23 | // March 2017 24 | // 25 | // # Algorithm 26 | // Only very few adjustments to problem 31: 27 | // - replace anything related to coins by the numbers 1..100 28 | // - finally subtract 1 because the sum has to consist of at least two numbers (not just one) 29 | // - for more details on the algorithm itself, please read my explanation of problem 31 30 | // 31 | // I am aware that there are more efficient solutions (even much shorter solutions !) but re-using old, 32 | // proven code is still the fastest way to solve a problem ... 33 | 34 | #include 35 | #include 36 | 37 | typedef std::vector combinations; 38 | 39 | int main() 40 | { 41 | const unsigned int MaxNumber = 1000; 42 | // remember combinations for all combinations from 1 up to 1000 43 | std::vector history; 44 | 45 | // store number of combinations in [x] if only summands up to x+1 are allowed: 46 | // [0] => combinations if only 1s are allowed 47 | // [1] => 1s and 2s are allowed, nothing more 48 | // [2] => 1s, 2s and 3s are allowed, nothing more 49 | // ... 50 | // [99] => all but 100 are allowed 51 | // [100] => using all numbers if possible 52 | 53 | unsigned int tests = 1; 54 | std::cin >> tests; 55 | while (tests--) 56 | { 57 | // number that should be represented as a sum 58 | unsigned int x = 100; 59 | std::cin >> x; 60 | 61 | // initially we start at zero 62 | // but if there are previous test cases then we can re-use the old results 63 | for (unsigned int j = history.size(); j <= x; j++) 64 | { 65 | combinations ways(MaxNumber, 0); 66 | 67 | // one combination if using only 1s 68 | ways[0] = 1; 69 | 70 | // use larger numbers, too 71 | for (unsigned int i = 1; i < MaxNumber; i++) 72 | { 73 | // first, pretend not to use that number 74 | ways[i] = ways[i - 1]; 75 | 76 | // now use that number once (if possible) 77 | auto current = i + 1; 78 | if (j >= current) 79 | { 80 | auto remaining = j - current; 81 | ways[i] += history[remaining][i]; 82 | } 83 | 84 | // only for Hackerrank 85 | // (it prevents printing huge numbers) 86 | ways[i] %= 1000000007; 87 | } 88 | 89 | // store information for future use 90 | history.push_back(ways); 91 | } 92 | 93 | // look up combinations 94 | auto result = history[x]; 95 | // the last column contains the desired value 96 | auto combinations = result.back(); 97 | 98 | // but it contains one undesired combination, too: the single number MaxNumber itself 99 | // (which fails to be "the sum of two (!) numbers", it's just one number) 100 | // therefore subtract 1 101 | combinations--; 102 | 103 | combinations %= 1000000007; // only for Hackerrank 104 | std::cout << combinations << std::endl; 105 | } 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /euler-0077.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Prime summations 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=77 7 | // http://euler.stephan-brumme.com/77/ 8 | // 9 | // # Problem 10 | // It is possible to write ten as the sum of primes in exactly five different ways: 11 | // 12 | // 7 + 3 13 | // 5 + 5 14 | // 5 + 3 + 2 15 | // 3 + 3 + 2 + 2 16 | // 2 + 2 + 2 + 2 + 2 17 | // 18 | // What is the first value which can be written as the sum of primes in over five thousand different ways? 19 | // 20 | // # Solved by 21 | // Stephan Brumme 22 | // March 2017 23 | // 24 | // # Algorithm 25 | // Instead of re-using the code from problem 76 (which was based on probem 31) I wrote this code from scratch 26 | // because the solution is actually much simpler than the previous challenges. 27 | // 28 | // Main idea: 29 | // ''combinations(x) = combinations(x - prime1) + combinations(x - prime2) + ...'' 30 | // I subtract each prime and look up ''combinations(x - currentPrime)'' and sum all those numbers 31 | // ==> nice Dynamic Programming solution ! 32 | 33 | #include 34 | #include 35 | 36 | int main() 37 | { 38 | const unsigned int MaxNumber = 1000; 39 | // store number of ways to represent a number as a sum of primes 40 | std::vector combinations(MaxNumber + 1, 0); 41 | // degenerated case 42 | combinations[0] = 1; 43 | 44 | // store all primes 45 | std::vector primes; 46 | for (unsigned int i = 2; i <= MaxNumber; i++) 47 | { 48 | bool isPrime = true; 49 | 50 | // test against all prime numbers we have so far (in ascending order) 51 | for (auto p : primes) 52 | { 53 | // next prime is too large to be a divisor ? 54 | if (p*p > i) 55 | break; 56 | 57 | // divisible ? => not prime 58 | if (i % p == 0) 59 | { 60 | isPrime = false; 61 | break; 62 | } 63 | } 64 | 65 | // only primes after this point ... 66 | if (!isPrime) 67 | continue; 68 | 69 | primes.push_back(i); 70 | 71 | // now add all solutions 72 | for (unsigned int pos = 0; pos <= MaxNumber - i; pos++) 73 | combinations[pos + i] += combinations[pos]; 74 | } 75 | 76 | //#define ORIGINAL 77 | #ifdef ORIGINAL 78 | // find first number with more than 5000 combinations 79 | for (size_t i = 0; i < combinations.size(); i++) 80 | if (combinations[i] > 5000) 81 | { 82 | std::cout << i << std::endl; 83 | break; 84 | } 85 | #else 86 | unsigned int tests = 1; 87 | std::cin >> tests; 88 | while (tests--) 89 | { 90 | // look up combinations 91 | unsigned int n; 92 | std::cin >> n; 93 | std::cout << combinations[n] << std::endl; 94 | } 95 | #endif 96 | 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /euler-0085.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Counting rectangles 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=85 7 | // http://euler.stephan-brumme.com/85/ 8 | // 9 | // # Problem 10 | // By counting carefully it can be seen that a rectangular grid measuring 3 by 2 contains eighteen rectangles: 11 | // 12 | // ![Examples](p085.gif) 13 | // 14 | // Although there exists no rectangular grid that contains exactly two million rectangles, find the area of the grid with the nearest solution. 15 | // 16 | // # Solved by 17 | // Stephan Brumme 18 | // March 2017 19 | // 20 | // # Algorithm 21 | // When you look at the "one-dimensional" case (an area with only 1 row): 22 | // || 3 || 6 || 4 || 23 | // || area || rectangles || total || 24 | // || 1x1 || 1 || 1 || 25 | // || 2x1 || 2+1 || 3 || 26 | // || 3x1 || 3+2+1 || 6 || 27 | // || 4x1 || 4+3+2+1 || 10 || 28 | // 29 | // These are the triangle numbers `T(x) = x * dfrac{x+1}{2}`, see https://en.wikipedia.org/wiki/Triangular_number 30 | // The same pattern appears in the 2D case with more than 1 row. 31 | // An area `A` contains: 32 | // `A(x,y) = T(x) * T(y) = dfrac{x(x+1)}{2} * dfrac{y(y+1)}{2}` 33 | // 34 | // `= dfrac{1}{4} xy * (x+1)(y+1)` 35 | // 36 | // Under the assumption that `y > x` I iterate over all `x` and `y` until I find the first area exceeding the limit. 37 | // Each subsequent grid can't yield a better solution because of `A(x,y+1) > A(x,y)`. 38 | // 39 | // The grid with the nearest solution is the grid where the number of rectangles `r` is is closest to 2000000, i.e. where `abs(r - 2000000)` is minimized. 40 | 41 | #include 42 | #include 43 | 44 | int main() 45 | { 46 | unsigned int tests = 1; 47 | std::cin >> tests; 48 | while (tests--) 49 | { 50 | unsigned int target = 2000000; 51 | std::cin >> target; 52 | 53 | // assume x <= y, therefore x <= sqrt(limit) 54 | unsigned int root = sqrt(target); 55 | unsigned int bestRectangles = 0; 56 | unsigned int bestArea = 0; 57 | for (unsigned int x = 1; x <= root + 1; x++) // allow slight overshooting 58 | { 59 | // start with a sqaure 60 | unsigned int y = x; 61 | // number of rectangles 62 | unsigned int rectangles = 0; 63 | 64 | // slowly increase y until too many rectangle in the grid 65 | do 66 | { 67 | unsigned int area = x * y; 68 | 69 | // the formula derived above 70 | rectangles = x * (x + 1) * y * (y + 1) / 4; 71 | 72 | // closer to desired number of rectangles than before ? 73 | if (abs(bestRectangles - target) > abs(rectangles - target)) 74 | { 75 | bestRectangles = rectangles; 76 | bestArea = area; 77 | } 78 | 79 | // prefer larger areas, too (additional requirement of Hackerrank) 80 | if (abs(bestRectangles - target) == abs(rectangles - target) && bestArea < area) 81 | bestArea = area; 82 | 83 | y++; 84 | } while (rectangles < target); 85 | 86 | // just a speed-up ... abortion when the inner loop exited with a square area x*y 87 | // => it means that no further solutions possible, area already too large 88 | if (y == x + 1) // plus one because y was incremented before leaving the inner loop 89 | break; 90 | } 91 | std::cout << bestArea << std::endl; 92 | } 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /euler-0087.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Prime power triples 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=87 7 | // http://euler.stephan-brumme.com/87/ 8 | // 9 | // # Problem 10 | // The smallest number expressible as the sum of a prime square, prime cube, and prime fourth power is 28. 11 | // In fact, there are exactly four numbers below fifty that can be expressed in such a way: 12 | // 13 | // `28 = 2^2 + 2^3 + 2^4` 14 | // `33 = 3^2 + 2^3 + 2^4` 15 | // `49 = 5^2 + 2^3 + 2^4` 16 | // `47 = 2^2 + 3^3 + 2^4` 17 | // 18 | // How many numbers below fifty million can be expressed as the sum of a prime square, prime cube, and prime fourth power? 19 | // 20 | // # Solved by 21 | // Stephan Brumme 22 | // March 2017 23 | // 24 | // # Algorithm 25 | // A simple prime sieve is responsible to find all primes `i < sqrt{50000000}`. 26 | // Then three nested loops compute all sums of all combinations of such primes where `a^2 + b^3 + c^4 < 50000000`. 27 | // Be careful: ''b*b*b'' and ''c*c*c*c'' can easily exceed an ''unsigned int''. 28 | // 29 | // Those sums are sorted and duplicate sums are removed. Now we have a nice ''std::vector'' with all sums. 30 | // The original problem is solved now (just display ''sums.size()'') but the Hackerrank problem is slightly tougher. 31 | // 32 | // # Hackerrank 33 | // In order to find the the number of sums which are below a certain input value, I search through the sorted container with ''std::upper_bound'' 34 | // and then compute the distance to the beginning of the container. 35 | // That's extremely fast (''std::upper_bound'' most likely uses binary search) and easily processed thousands of test cases per second. 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | int main() 42 | { 43 | const unsigned int MaxLimit = 100 * 1000 * 1000; // Hackerrank: 10^7 instead of 5*10^6 44 | 45 | // prime sieve 46 | std::vector primes; 47 | primes.push_back(2); 48 | for (unsigned int i = 3; i*i < MaxLimit; i += 2) 49 | { 50 | bool isPrime = true; 51 | 52 | // test against all prime numbers we have so far (in ascending order) 53 | for (auto p : primes) 54 | { 55 | // next prime is too large to be a divisor ? 56 | if (p*p > i) 57 | break; 58 | 59 | // divisible ? => not prime 60 | if (i % p == 0) 61 | { 62 | isPrime = false; 63 | break; 64 | } 65 | } 66 | 67 | // yes, we have a prime number 68 | if (isPrime) 69 | primes.push_back(i); 70 | } 71 | 72 | // just three nested loops where I generate all sums 73 | std::vector sums; 74 | for (auto a : primes) 75 | for (auto b : primes) 76 | for (auto c : primes) 77 | { 78 | auto a2 = a*a; 79 | auto b3 = (unsigned long long)b*b*b; 80 | auto c4 = (unsigned long long)c*c*c*c; 81 | auto sum = a2 + b3 + c4; 82 | // abort if too big 83 | if (sum > MaxLimit) 84 | break; 85 | 86 | sums.push_back(sum); 87 | } 88 | 89 | // sort ascendingly 90 | std::sort(sums.begin(), sums.end()); 91 | // a few sums occur twice, let's remove them ! 92 | auto last = std::unique(sums.begin(), sums.end()); 93 | 94 | // process test cases 95 | unsigned int tests = 1; 96 | std::cin >> tests; 97 | while (tests--) 98 | { 99 | unsigned int limit = MaxLimit; 100 | std::cin >> limit; 101 | 102 | // find next sum which is bigger than the limit 103 | auto pos = std::upper_bound(sums.begin(), last, limit); 104 | // how many sums are inbetween 28 and limit ? 105 | auto num = std::distance(sums.begin(), pos); 106 | std::cout << num << std::endl; 107 | } 108 | 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /euler-0097.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Large non-Mersenne prime 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=97 7 | // http://euler.stephan-brumme.com/97/ 8 | // 9 | // # Problem 10 | // The first known prime found to exceed one million digits was discovered in 1999, 11 | // and is a Mersenne prime of the form `2^6972593 - 1`; it contains exactly 2,098,960 digits. 12 | // Subsequently other Mersenne primes, of the form `2^p - 1`, have been found which contain more digits. 13 | // 14 | // However, in 2004 there was found a massive non-Mersenne prime which contains 2,357,207 digits: `28433 * 2^7830457 + 1`. 15 | // 16 | // Find the last ten digits of this prime number. 17 | // 18 | // # Solved by 19 | // Stephan Brumme 20 | // March 2017 21 | // 22 | // # Algorithm 23 | // I used ''powmod'' in problem 48 to compute `a^b mod c` (see there for an explanation of the way ''powmod'' works). 24 | // Unfortunately we have to find the 10 last digits, which is one digit too much for 32/64 bit multiplications. 25 | // GCC's support for 64/128 arithmetic solves this problem easily. 26 | // 27 | // # Alternative 28 | // I could have used my old ''powmod'' code which relies on ''mulmod'' but that code is too slow for the Hackerrank version of this problem. 29 | // On the contrary, that code from problem 48 is more portable. 30 | 31 | #include 32 | #include 33 | 34 | // GCC only !!! 35 | typedef unsigned __int128 BigNum; 36 | 37 | //#define ORIGINAL 38 | #ifdef ORIGINAL 39 | const unsigned int Digits = 10; 40 | const BigNum Modulo = 10000000000ULL; 41 | #else 42 | const unsigned int Digits = 12; 43 | const BigNum Modulo = 1000000000000ULL; 44 | #endif 45 | 46 | // compute the n-th power of a big number (n >= 0) 47 | BigNum powmod(BigNum base, unsigned int exponent, BigNum modulo) 48 | { 49 | BigNum result = 1; 50 | while (exponent > 0) 51 | { 52 | // fast exponentiation 53 | if (exponent & 1) 54 | result = (result * base) % modulo; 55 | 56 | base = (base * base) % modulo; 57 | exponent >>= 1; 58 | } 59 | return result; 60 | } 61 | 62 | int main() 63 | { 64 | unsigned long long sum = 0; 65 | 66 | unsigned int tests = 1; 67 | std::cin >> tests; 68 | while (tests--) 69 | { 70 | // read a * b^c + d 71 | unsigned long long factor, base, exponent, add; 72 | std::cin >> factor >> base >> exponent >> add; 73 | 74 | // compute result 75 | unsigned long long result = (powmod(base, exponent, Modulo) * factor + add) % Modulo; 76 | 77 | // modulo all the way ... we need only the last 10 (or 12) digits 78 | sum += result; 79 | sum %= Modulo; 80 | } 81 | 82 | // print with leading zeros 83 | std::cout << std::setfill('0') << std::setw(Digits) << sum; 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /euler-0099.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Largest exponential 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=99 7 | // http://euler.stephan-brumme.com/99/ 8 | // 9 | // # Problem 10 | // Comparing two numbers written in index form like `2^11` and `3^7` is not difficult, as any calculator would confirm that `2^11 = 2048 < 3^7 = 2187`. 11 | // 12 | // However, confirming that `632382^518061 > 519432^525806` would be much more difficult, as both numbers contain over three million digits. 13 | // 14 | // Using [base_exp.txt](https://projecteuler.net/project/resources/p099_base_exp.txt) (right click and 'Save Link/Target As...'), a 22K text file containing one thousand lines with a base/exponent pair on each line, 15 | // determine which line number has the greatest numerical value. 16 | // 17 | // NOTE: The first two lines in the file represent the numbers in the example given above. 18 | // 19 | // # Solved by 20 | // Stephan Brumme 21 | // March 2017 22 | // 23 | // # Algorithm 24 | // If `a^b < x^y` then `log{a^b} < log{x^y}` which means `b * log{a} < y * log{x}`. 25 | // The logarithm fits easily in a ''double''. 26 | // 27 | // ''std::map'' is an ascendingly sorted container ==> its last element has the greatest numerical value. 28 | // 29 | // # Hackerrank 30 | // Print the base and exponent of the k-sorted element. 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #define ORIGINAL 37 | 38 | int main() 39 | { 40 | #ifdef ORIGINAL 41 | // read all 1000 pairs, store [logarithm] => [index] 42 | std::map data; 43 | for (unsigned int i = 1; i <= 1000; i++) // first line has index 1 (not 0) 44 | { 45 | unsigned int base, exponent; 46 | char comma; // skip commas in input file 47 | std::cin >> base >> comma >> exponent; 48 | 49 | // sort by exponent * log(base) 50 | data[exponent * log(base)] = i; 51 | } 52 | // return index of last input line 53 | std::cout << data.rbegin()->second << std::endl; 54 | 55 | return 0; 56 | 57 | #else 58 | 59 | // how many pairs ? 60 | unsigned int numbers; 61 | std::cin >> numbers; 62 | 63 | // read all pairs, store [logarithm] => [base, exponent] 64 | std::map> data; 65 | for (unsigned int i = 1; i <= numbers; i++) 66 | { 67 | unsigned int base, exponent; 68 | std::cin >> base >> exponent; 69 | data[exponent * log(base)] = std::make_pair(base, exponent); 70 | } 71 | 72 | // which number of the sorted list should be printed ? 73 | unsigned int pos; 74 | std::cin >> pos; 75 | 76 | // std::map is sorted, jump to the position 77 | auto i = data.begin(); 78 | std::advance(i, pos - 1); // input is 1-based 79 | 80 | // get result 81 | auto result = i->second; 82 | auto base = result.first; 83 | auto exponent = result.second; 84 | // and print it 85 | std::cout << base << " " << exponent << std::endl; 86 | 87 | return 0; 88 | #endif 89 | } 90 | -------------------------------------------------------------------------------- /euler-0112.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Bouncy numbers 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=112 7 | // http://euler.stephan-brumme.com/112/ 8 | // 9 | // # Problem 10 | // Working from left-to-right if no digit is exceeded by the digit to its left it is called an increasing number; for example, 134468. 11 | // Similarly if no digit is exceeded by the digit to its right it is called a decreasing number; for example, 66420. 12 | // We shall call a positive integer that is neither increasing nor decreasing a "bouncy" number; for example, 155349. 13 | // Clearly there cannot be any bouncy numbers below one-hundred, but just over half of the numbers below one-thousand (525) are bouncy. 14 | // In fact, the least number for which the proportion of bouncy numbers first reaches 50% is 538. 15 | // 16 | // Surprisingly, bouncy numbers become more and more common and by the time we reach 21780 the proportion of bouncy numbers is equal to 90%. 17 | // 18 | // Find the least number for which the proportion of bouncy numbers is exactly 99%. 19 | // 20 | // # Solved by 21 | // Stephan Brumme 22 | // May 2017 23 | // 24 | // # Algorithm 25 | // ''isBouncy'' determines whether its parameter is bouncy or not by stepping through its digits. 26 | // The rest is just a brute-force search. 27 | // 28 | // # Hackerrank 29 | // Any percentage can be entered. 30 | // Even though my brute-force search finds the solution to the original problem (99%) in less than 0.1 seconds, it's way too slow for 31 | // the potentially huge search space of Hackerrank. Someone indicated that one "answer requires about 90 bits". 32 | 33 | #include 34 | 35 | // return true if x is a bouncy number 36 | bool isBouncy(unsigned long long x) 37 | { 38 | // figure out whether x is monotonic ascending or descending 39 | // it's bouncy if neither ascending nor descending 40 | bool ascending = true; 41 | bool descending = true; 42 | 43 | // initial digit (the right-most digit) 44 | auto previous = x % 10; 45 | x /= 10; 46 | 47 | // still digits left ? 48 | while (x > 0) 49 | { 50 | // current digit 51 | auto current = x % 10; 52 | 53 | // compare two digits 54 | descending &= previous >= current; 55 | ascending &= previous <= current; 56 | 57 | // bouncy ? 58 | if (!ascending && !descending) 59 | return true; 60 | 61 | // keep going ... 62 | x /= 10; 63 | previous = current; 64 | } 65 | 66 | // not bouncy (either ascending, descending or all digits are equal) 67 | return false; 68 | } 69 | 70 | 71 | int main() 72 | { 73 | unsigned int tests = 1; 74 | std::cin >> tests; 75 | 76 | while (tests--) 77 | { 78 | // original problem: 99% 79 | unsigned long long p = 99; 80 | unsigned long long q = 100; 81 | std::cin >> p >> q; 82 | 83 | // brute-force ... 84 | unsigned long long current = 100; // no bouncy numbers below 100 85 | unsigned long long numBouncy = 0; 86 | do 87 | { 88 | // check next number if bouncy 89 | current++; 90 | if (isBouncy(current)) 91 | numBouncy++; 92 | } while (numBouncy * q < current * p); // same as numBouncy/current == p/q (=99%) 93 | 94 | // print result 95 | std::cout << current << std::endl; 96 | } 97 | 98 | return 0; 99 | } 100 | -------------------------------------------------------------------------------- /euler-0114.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Counting block combinations I 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=114 7 | // http://euler.stephan-brumme.com/114/ 8 | // 9 | // # Problem 10 | // A row measuring seven units in length has red blocks with a minimum length of three units placed on it, 11 | // such that any two red blocks (which are allowed to be different lengths) are separated by at least one black square. 12 | // There are exactly seventeen ways of doing this. 13 | // 14 | // ![pattern](pattern.gif) 15 | // 16 | // How many ways can a row measuring fifty units in length be filled? 17 | // 18 | // NOTE: Although the example above does not lend itself to the possibility, in general it is permitted to mix block sizes. 19 | // For example, on a row measuring eight units in length you could use red (3), black (1), and red (4). 20 | // 21 | // # Solved by 22 | // Stephan Brumme 23 | // May 2017 24 | // 25 | // # Algorithm 26 | // This is a nice Dynamic Programming problem: 27 | // - if there are less than three cells available then all must be black (1 solution) 28 | // - else: the next cell can be black (return ''count[space - 1]'') 29 | // - or: the next cells can be red, try all possible lengths and add ''count[space - block]'' 30 | // 31 | // The algorithm examines most row lengths multiple times but memoizing the results in ''solutions'' keeps the running time well below 0.01 seconds. 32 | // 33 | // # Hackerrank 34 | // My approach needs a bit of memory. Hackerrank has inputs up to `10^18` which clearly exceeds the RAM size of a desktop PC. 35 | // [TODO] find closed formula 36 | 37 | #include 38 | #include 39 | 40 | #define ORIGINAL 41 | 42 | // memoized solutions 43 | const long long Unknown = -1; 44 | std::vector solutions; 45 | 46 | // print result modulo some number 47 | #ifndef ORIGINAL 48 | const unsigned long long Modulo = 1000000007; 49 | #endif 50 | 51 | // find result for row with a certain length 52 | unsigned long long count(unsigned long long space, unsigned int minBlockLength) 53 | { 54 | // finished ? 55 | if (space == 0) 56 | return 1; 57 | 58 | // already know the answer ? 59 | if (solutions[space] != Unknown) 60 | return solutions[space]; 61 | 62 | // one option is to leave the next cell black 63 | auto result = count(space - 1, minBlockLength); 64 | // insert red blocks at the current position with all possible spaces 65 | for (auto block = minBlockLength; block <= space; block++) 66 | { 67 | // how much is left after inserting ? 68 | auto next = space - block; 69 | // must be followed by a black cell 70 | if (next > 0) 71 | next--; 72 | 73 | // count all combinations 74 | result += count(next, minBlockLength); 75 | } 76 | 77 | // Hackerrank only 78 | #ifndef ORIGINAL 79 | result %= Modulo; 80 | #endif 81 | 82 | // memoize result 83 | solutions[space] = result; 84 | return result; 85 | } 86 | 87 | int main() 88 | { 89 | // minimum length of each red block 90 | unsigned int minBlockLength = 3; 91 | // size of the whole row 92 | unsigned long long totalLength = 50; 93 | std::cin >> totalLength >> minBlockLength; 94 | 95 | // cached results 96 | solutions.resize(totalLength + 1, Unknown); 97 | 98 | // let's go ! 99 | std::cout << count(totalLength, minBlockLength) << std::endl; 100 | 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /euler-0115.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Counting block combinations II 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=115 7 | // http://euler.stephan-brumme.com/115/ 8 | // 9 | // # Problem 10 | // NOTE: This is a more difficult version of Problem 114. 11 | // 12 | // A row measuring n units in length has red blocks with a minimum length of m units placed on it, 13 | // such that any two red blocks (which are allowed to be different lengths) are separated by at least one black square. 14 | // 15 | // Let the fill-count function, F(m, n), represent the number of ways that a row can be filled. 16 | // 17 | // For example, F(3, 29) = 673135 and F(3, 30) = 1089155. 18 | // 19 | // That is, for m = 3, it can be seen that n = 30 is the smallest value for which the fill-count function first exceeds one million. 20 | // 21 | // In the same way, for m = 10, it can be verified that F(10, 56) = 880711 and F(10, 57) = 1148904, so n = 57 is the least value for which the fill-count function first exceeds one million. 22 | // 23 | // For m = 50, find the least value of n for which the fill-count function first exceeds one million. 24 | // 25 | // # Solved by 26 | // Stephan Brumme 27 | // May 2017 28 | // 29 | // # Algorithm 30 | // ... almost the same as problem 114 ! 31 | // Only the ''main'' function had to adjusted to find in a simple loop the smallest value to exceed one million. 32 | // 33 | // # Hackerrank 34 | // My approach needs a bit of memory. Hackerrank has inputs up to `10^18` which clearly exceed the RAM size of a desktop PC. 35 | // [TODO] find closed formula 36 | 37 | #include 38 | #include 39 | 40 | #define ORIGINAL 41 | 42 | // memoized solutions 43 | const long long Unknown = -1; 44 | std::vector solutions; 45 | 46 | // find result for row with a certain length 47 | unsigned long long count(unsigned long long space, unsigned int minBlockLength) 48 | { 49 | // finished ? 50 | if (space == 0) 51 | return 1; 52 | 53 | // already know the answer ? 54 | if (solutions[space] != Unknown) 55 | return solutions[space]; 56 | 57 | // one option is to leave the next cell black 58 | auto result = count(space - 1, minBlockLength); 59 | // insert red blocks at the current position with all possible spaces 60 | for (auto block = minBlockLength; block <= space; block++) 61 | { 62 | // how much is left after inserting ? 63 | auto next = space - block; 64 | // must be followed by a black cell 65 | if (next > 0) 66 | next--; 67 | 68 | // count all combinations 69 | result += count(next, minBlockLength); 70 | } 71 | 72 | // memoize result 73 | solutions[space] = result; 74 | return result; 75 | } 76 | 77 | int main() 78 | { 79 | unsigned int tests; 80 | std::cin >> tests; 81 | while (tests--) 82 | { 83 | // minimum length of each red block 84 | unsigned int minBlockLength = 3; 85 | // what number should be exceeded ? 86 | unsigned long long limit = 1000000; 87 | 88 | std::cin >> minBlockLength >> limit; 89 | 90 | // cached results 91 | solutions.clear(); 92 | solutions.resize(limit + 1, Unknown); // not enough for Hackerrank 93 | 94 | for (unsigned int totalLength = 1; ; totalLength++) 95 | { 96 | auto combinations = count(totalLength, minBlockLength); 97 | if (combinations > limit) 98 | { 99 | std::cout << totalLength << std::endl; 100 | break; 101 | } 102 | } 103 | } 104 | 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /euler-0116.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Red, green or blue tiles 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=116 7 | // http://euler.stephan-brumme.com/116/ 8 | // 9 | // # Problem 10 | // A row of five black square tiles is to have a number of its tiles replaced with coloured oblong tiles chosen from red (length two), green (length three), or blue (length four). 11 | // 12 | // If red tiles are chosen there are exactly seven ways this can be done. 13 | // 14 | // ![red tiles](red.gif) 15 | // 16 | // If green tiles are chosen there are three ways. 17 | // 18 | // ![green tiles](green.gif) 19 | // 20 | // And if blue tiles are chosen there are two ways. 21 | // 22 | // ![blue tiles](blue.gif) 23 | // 24 | // Assuming that colours cannot be mixed there are 7 + 3 + 2 = 12 ways of replacing the black tiles in a row measuring five units in length. 25 | // 26 | // How many different ways can the black tiles in a row measuring fifty units in length be replaced if colours cannot be mixed and at least one coloured tile must be used? 27 | // 28 | // NOTE: This is related to Problem 117. 29 | // 30 | // # Solved by 31 | // Stephan Brumme 32 | // May 2017 33 | // 34 | // # Algorithm 35 | // The row is filling with an arbitrary sequence of black and colored blocks. 36 | // The length of the sequence is the sum of black and colored blocks. 37 | // For a known number of black and colored blocks, this is: 38 | // `{black+colored}choose{black}` `= dfrac{(black+colored)!}{black!colored!}` 39 | // 40 | // It took me a little bit to write a ''choose'' function such that the factorials don't overflow too soon. 41 | // 42 | // # Hackerrank 43 | // As always, Hackerrank's input is ridiculously high and my poor C++ data types can't handle such numbers. 44 | // [TODO] find closed formula 45 | 46 | #include 47 | #include 48 | 49 | #define ORIGINAL 50 | 51 | // number of ways to choose n elements from k available 52 | unsigned long long choose(unsigned long long n, unsigned long long k) 53 | { 54 | // n! / (n-k)!k! 55 | unsigned long long result = 1; 56 | // reduce overflow by dividing as soon as possible to keep numbers small 57 | for (unsigned long long invK = 1; invK <= k; invK++) 58 | { 59 | result *= n; 60 | result /= invK; 61 | n--; 62 | } 63 | return result; 64 | } 65 | 66 | int main() 67 | { 68 | unsigned int tests; 69 | std::cin >> tests; 70 | while (tests--) 71 | { 72 | // length of row 73 | unsigned int totalLength = 50; 74 | std::cin >> totalLength; 75 | 76 | unsigned long long sum = 0; 77 | // try all four block lengths 78 | for (unsigned int blockLength = 2; blockLength <= 4; blockLength++) 79 | { 80 | // maximum number of blocks of the current size 81 | auto maxBlocks = totalLength / blockLength; 82 | 83 | // insert 1 to maxBlocks colored blocks 84 | for (unsigned int colored = 1; colored <= maxBlocks; colored++) 85 | { 86 | // remaining black tiles 87 | auto black = totalLength - colored * blockLength; 88 | // total number of black and colored tiles 89 | auto tiles = black + colored; 90 | // count combinations 91 | auto combinations = choose(tiles, colored); 92 | sum += combinations; 93 | 94 | #ifndef ORIGINAL 95 | // Hackerrank only 96 | sum %= 1000000007; 97 | #endif 98 | } 99 | } 100 | 101 | std::cout << sum << std::endl; 102 | } 103 | 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /euler-0117.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Red, green, and blue tiles 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=117 7 | // http://euler.stephan-brumme.com/117/ 8 | // 9 | // # Problem 10 | // Using a combination of black square tiles and oblong tiles chosen from: red tiles measuring two units, green tiles measuring three units, and blue tiles measuring four units, it is possible to tile a row measuring five units in length in exactly fifteen different ways. 11 | // 12 | // ![tiles](pattern.gif) 13 | // 14 | // How many ways can a row measuring fifty units in length be tiled? 15 | // 16 | // NOTE: This is related to Problem 116. 17 | // 18 | // # Solved by 19 | // Stephan Brumme 20 | // May 2017 21 | // 22 | // # Algorithm 23 | // ... almost the same as problem 115 ! 24 | // Actually the code is even shorter - the ''for''-loop in ''count'' runs from 1 to 4 (1 = black, 2 = red, 3 = green, 4 = blue). 25 | // There are no "gaps" between tiles because I treat black tiles the same way like any other tile. 26 | // 27 | // These numbers are also called "Generalized Fibonacci numbers", and the special case for this problem is called [Tetranacci numbers](https://en.wikipedia.org/wiki/Generalizations_of_Fibonacci_numbers#Tetranacci_numbers). 28 | // 29 | // # Hackerrank 30 | // As always, Hackerrank's input is ridiculously high and my poor C++ data types can't handle such numbers. 31 | // [TODO] find closed formula 32 | 33 | #include 34 | #include 35 | 36 | #define ORIGINAL 37 | 38 | // memoized solutions 39 | const long long Unknown = -1; 40 | std::vector solutions; 41 | 42 | // find result for row with a certain length 43 | unsigned long long count(unsigned long long space) 44 | { 45 | // finished ? 46 | if (space == 0) 47 | return 1; 48 | 49 | // already know the answer ? 50 | if (solutions[space] != Unknown) 51 | return solutions[space]; 52 | 53 | // insert red blocks at the current position with all possible spaces 54 | unsigned long long result = 0; 55 | for (unsigned long long block = 1; block <= 4 && block <= space; block++) 56 | { 57 | // how much is left after inserting ? 58 | auto next = space - block; 59 | 60 | // count all combinations 61 | result += count(next); 62 | } 63 | 64 | // memoize result 65 | solutions[space] = result; 66 | return result; 67 | } 68 | 69 | int main() 70 | { 71 | unsigned int tests; 72 | std::cin >> tests; 73 | while (tests--) 74 | { 75 | // what number should be exceeded ? 76 | unsigned long long limit = 50; 77 | std::cin >> limit; 78 | 79 | // cached results 80 | solutions.clear(); 81 | solutions.resize(limit+1, Unknown); 82 | 83 | auto result = count(limit); 84 | #ifndef ORIGINAL 85 | result %= 1000000007; // Hackerrank asks for "small" results 86 | #endif 87 | 88 | std::cout << result << std::endl; 89 | } 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /euler-0123.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Prime square remainders 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=123 7 | // http://euler.stephan-brumme.com/123/ 8 | // 9 | // # Problem 10 | // Let `p_n` be the `n`th prime: 2, 3, 5, 7, 11, ..., and let `r` be the remainder when `(p_n-1)^n + (p_n+1)^n` is divided by `pn^2`. 11 | // 12 | // For example, when `n = 3`, `p^3 = 5`, and `4^3 + 6^3 = 280 == 5 mod 25`. 13 | // 14 | // The least value of n for which the remainder first exceeds `10^9` is 7037. 15 | // 16 | // Find the least value of `n` for which the remainder first exceeds `10^10`. 17 | // 18 | // # Solved by 19 | // Stephan Brumme 20 | // May 2017 21 | // 22 | // # Algorithm 23 | // This is basically problem 120 merged with a prime sieve. 24 | // My algorithm description of problem 120 explains why the maximum remainder is `2na` (and `a` is a prime in the current problem). 25 | // 26 | // # Note 27 | // There is no need to check the first 7036 prime numbers because the problem statement mentioned that all of them produce a remainder `<10^9`. 28 | // But the computation is so simple and fast that it doesn't affect the execution time at all. 29 | // 30 | // I prefer a prime sieve based on trial division because it can be computed incrementally without knowing an upper limit beforehand 31 | // (which is a must for the sieve of Eratosthenes). 32 | 33 | #include 34 | #include 35 | 36 | int main() 37 | { 38 | // sieve based on trial division 39 | std::vector primes = { 2 }; 40 | for (unsigned int i = 3; ; i += 2) 41 | { 42 | bool isPrime = true; 43 | 44 | // test against all prime numbers we have so far (in ascending order) 45 | for (auto p : primes) 46 | { 47 | // next prime is too large to be a divisor ? 48 | if (p*p > i) 49 | break; 50 | 51 | // divisible ? => not prime 52 | if (i % p == 0) 53 | { 54 | isPrime = false; 55 | break; 56 | } 57 | } 58 | 59 | // no prime ? 60 | if (!isPrime) 61 | continue; 62 | 63 | primes.push_back(i); 64 | 65 | // only every "odd" prime 66 | if (primes.size() % 2 == 0) 67 | continue; 68 | 69 | // compute remainder 70 | auto remainder = 2 * i * primes.size(); 71 | // exceeds 10^10 ? 72 | if (remainder >= 10000000000ULL) 73 | break; 74 | } 75 | 76 | // print result 77 | std::cout << primes.size() << std::endl; 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /euler-0129.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Repunit divisibility 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=129 7 | // http://euler.stephan-brumme.com/129/ 8 | // 9 | // # Problem 10 | // A number consisting entirely of ones is called a repunit. We shall define `R(k)` to be a repunit of length `k`; for example, `R(6) = 111111`. 11 | // 12 | // Given that `n` is a positive integer and `GCD(n, 10) = 1`, it can be shown that there always exists a value, `k`, for which `R(k)` is divisible by n, 13 | // and let `A(n)` be the least such value of `k`; for example, `A(7) = 6` and `A(41) = 5`. 14 | // 15 | // The least value of `n` for which `A(n)` first exceeds ten is 17. 16 | // 17 | // Find the least value of `n` for which `A(n)` first exceeds one-million. 18 | // 19 | // # Solved by 20 | // Stephan Brumme 21 | // May 2017 22 | // 23 | // # Algorithm 24 | // Only if `x` is a divisor of `y` then `y mod x == 0`. 25 | // My code generates all repunits `R(k)` until `R(k) mod x == 0`: 26 | // `R(k+1) = R(k) * 10 + 1` 27 | // 28 | // Unfortunately, `R(20)` is already too big for a 64 bit integer. 29 | // But I don't actually need to work with `R(k)`, I can use its `mod x`, too: 30 | // `R(k) mod x = R_{mod x}(k) mod x` 31 | // `R_{mod x}(k+1) = (R_{mod x}(k) * 10 + 1) mod x` 32 | // 33 | // `x` fits easily in a 32 bit integer, therefore the "modulo repunit" fits in there, too. 34 | // 35 | // Initially I started a brute-force search with ''i = 1'' which took a few minutes. However, it seems that always `A(i) <= i`. 36 | // 37 | // # Hackerrank 38 | // Apparently there is a much smarter way to solve this - that I have no idea about. All but the first test case time out. 39 | 40 | #define ORIGINAL 41 | 42 | #include 43 | 44 | // return minimum k where R(k) is divisible by x 45 | unsigned long long getMinK(unsigned long long x) 46 | { 47 | // same as gcd(x, 10) = 1 48 | if (x % 5 == 0 || x % 2 == 0) 49 | return 0; 50 | 51 | // "number of ones" 52 | unsigned long long result = 1; 53 | // current repunit mod divisor 54 | unsigned long long repunit = 1; 55 | // no remainder ? that repunit can be divided by divisor 56 | while (repunit != 0) 57 | { 58 | // next repunit 59 | repunit *= 10; 60 | repunit++; 61 | // keep it mod divisor 62 | repunit %= x; 63 | 64 | result++; 65 | } 66 | 67 | return result; 68 | } 69 | 70 | int main() 71 | { 72 | unsigned int tests; 73 | std::cin >> tests; 74 | while (tests--) 75 | { 76 | // I observed that getMinK(i) <= i 77 | // I lack the mathematic skills to prove (or disprove) it 78 | // at least it holds up to the result when running a brute-force search beginning at 1 79 | unsigned long long limit = 1000000; 80 | std::cin >> limit; 81 | unsigned long long i = limit; 82 | 83 | #ifdef ORIGINAL 84 | while (getMinK(i) <= limit) 85 | i++; 86 | std::cout << i << std::endl; 87 | #else 88 | std::cout << getMinK(i) << std::endl; 89 | #endif 90 | } 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /euler-0132.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Large repunit factors 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=132 7 | // http://euler.stephan-brumme.com/132/ 8 | // 9 | // # Problem 10 | // A number consisting entirely of ones is called a repunit. We shall define `R(k)` to be a repunit of length `k`. 11 | // 12 | // For example, `R(10) = 1111111111 = 11 * 41 * 271 * 9091`, and the sum of these prime factors is 9414. 13 | // 14 | // Find the sum of the first forty prime factors of `R(10^9)`. 15 | // 16 | // # Solved by 17 | // Stephan Brumme 18 | // June 2017 19 | // 20 | // # Algorithm 21 | // This problem was a tough one for me. I didn't realize that `R(k) = dfrac{10^k - 1}{9}` until I saw that equation on https://en.wikipedia.org/wiki/Repunit 22 | // 23 | // The task is to find prime factors `p` such that `R(k) == 0 mod p`. 24 | // Which becomes (using the formula from Wikipedia): 25 | // `dfrac{10^k - 1}{9} == 0 mod p` 26 | // 27 | // `10^k - 1 == 0 mod 9p` 28 | // `10^k == 1 mod 9p` 29 | // 30 | // `k` is quite small, therefore a simplified version of my ''powmod'' function (see my [toolbox](../toolbox/#powmod) ) can easily compute ''10^k mod 9p''. 31 | // If it returns 1, then ''p'' is added to ''sum'' until 40 factors are found. 32 | // 33 | // # Note 34 | // My live tests allows you to enter different `k` and change the number of relevant prime factors, too (which is 40 in the original problem). 35 | 36 | #include 37 | #include 38 | 39 | // return (base^exponent) % modulo 40 | unsigned int powmod(unsigned int base, unsigned int exponent, unsigned int modulo) 41 | { 42 | unsigned int result = 1; 43 | while (exponent > 0) 44 | { 45 | // fast exponentation: 46 | // odd exponent ? a^b = a*a^(b-1) 47 | if (exponent & 1) 48 | result = (result * (unsigned long long)base) % modulo; // enforce 64-multiplication 49 | 50 | // even exponent ? a^b = (a*a)^(b/2) 51 | base = (base * (unsigned long long)base) % modulo; // enforce 64-multiplication 52 | exponent >>= 1; 53 | } 54 | return result; 55 | } 56 | 57 | int main() 58 | { 59 | unsigned int numFactors = 40; 60 | unsigned long long digits = 1000000000; 61 | std::cin >> digits >> numFactors; 62 | 63 | unsigned int sum = 0; 64 | std::vector primes = { 2 }; // two is never a prime factor of a repunit 65 | for (unsigned int i = 3; numFactors > 0; i++) 66 | { 67 | bool isPrime = true; 68 | 69 | // test against all prime numbers we have so far (in ascending order) 70 | for (auto x : primes) 71 | { 72 | // prime is too large to be a divisor 73 | if (x*x > i) 74 | break; 75 | 76 | // divisible => not prime 77 | if (i % x == 0) 78 | { 79 | isPrime = false; 80 | break; 81 | } 82 | } 83 | 84 | // no prime 85 | if (!isPrime) 86 | continue; 87 | 88 | primes.push_back(i); 89 | 90 | // check for divisibility by 9*prime 91 | auto modulo = 9 * i; 92 | // remainder must be 1 93 | auto remainder = powmod(10, digits, modulo); 94 | if (remainder == 1) 95 | { 96 | sum += i; 97 | numFactors--; 98 | } 99 | 100 | // don't analyze huge primes 101 | // => not needed for the original problem, but avoids malicious input in live test 102 | // => e.g. user asks for more primes than the repunit has 103 | if (i > 1111111) 104 | break; 105 | } 106 | 107 | std::cout << sum << std::endl; 108 | 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /euler-0135.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Same differences 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=135 7 | // http://euler.stephan-brumme.com/135/ 8 | // 9 | // # Problem 10 | // Given the positive integers, `x`, `y`, and `z`, are consecutive terms of an arithmetic progression, the least value of the positive integer, `n`, 11 | // for which the equation, `x^2 - y^2 - z^2 = n`, has exactly two solutions is `n = 27`: 12 | // 13 | // `34^2 - 27^2 - 20^2 = 12^2 - 9^2 - 6^2 = 27` 14 | // 15 | // It turns out that n = 1155 is the least value which has exactly ten solutions. 16 | // 17 | // How many values of `n` less than one million have exactly ten distinct solutions? 18 | // 19 | // # Solved by 20 | // Stephan Brumme 21 | // May 2017 22 | // 23 | // # Algorithm 24 | // Let's assume `y = a`, `x = a + b` and `z = a - b`. Then I have to solve: 25 | // `(a + b)^2 - a^2 - (a - b)^2` 26 | // `= a^2 + 2ab + b^2 - a^2 - a^2 + 2ab - b^2` 27 | // `= 4ab - a^2` 28 | // `= a(4b - a)` 29 | // 30 | // All variables are positive integers, therefore `1 <= a < n`. 31 | // The value inside the brackets has to be positive, too, and `b` must be lower than `a` such that `\lceil frac{a}{4} \rceil <= b < a` 32 | // 33 | // Finally, iterating over all ''solutions'' and counting how often 10 occurs given the desired result. 34 | // 35 | // # Hackerrank 36 | // Just print how many solutions exists for a given input. The upper limit is 8 million (inclusive) opposed to one million (exclusive) of the original problem. 37 | 38 | #include 39 | #include 40 | 41 | //#define ORIGINAL 42 | 43 | int main() 44 | { 45 | #ifdef ORIGINAL 46 | unsigned int limit = 1000000; // "less than one million" 47 | #else 48 | unsigned int limit = 8000001; // up to 8 million (inclusive) 49 | #endif 50 | 51 | // precompute solutions 52 | std::vector solutions(limit, 0); 53 | for (unsigned int a = 1; a < limit; a++) 54 | for (auto b = (a + 3) / 4; b < a; b++) 55 | { 56 | auto current = a * (4*b - a); 57 | if (current >= limit) 58 | break; 59 | 60 | solutions[current]++; 61 | } 62 | 63 | #ifdef ORIGINAL 64 | // count all with exactly 10 solutions 65 | unsigned int count = 0; 66 | for (auto s : solutions) 67 | if (s == 10) 68 | count++; 69 | std::cout << count << std::endl; 70 | 71 | #else 72 | 73 | // look up number of solutions 74 | unsigned int tests; 75 | std::cin >> tests; 76 | while (tests--) 77 | { 78 | unsigned int pos; 79 | std::cin >> pos; 80 | std::cout << solutions[pos] << std::endl; 81 | } 82 | #endif 83 | 84 | return 0; 85 | } 86 | -------------------------------------------------------------------------------- /euler-0136.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Singleton differences 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=136 7 | // http://euler.stephan-brumme.com/136/ 8 | // 9 | // # Problem 10 | // The positive integers, `x`, `y`, and `z`, are consecutive terms of an arithmetic progression. 11 | // Given that `n` is a positive integer, the equation, `x^2 - y^2 - z^2 = n`, has exactly one solution when `n = 20`: 12 | // 13 | // `13^2 - 10^2 - 7^2 = 20` 14 | // 15 | // In fact there are twenty-five values of `n` below one hundred for which the equation has a unique solution. 16 | // 17 | // How many values of `n` less than fifty million have exactly one solution? 18 | // 19 | // # Solved by 20 | // Stephan Brumme 21 | // May 2017 22 | // 23 | // # Algorithm 24 | // My solution is almost identical to problem 135. See there for an explanation of the algorithm. 25 | // I actually submitted the correct solution to this problem just four minutes after. 26 | // 27 | // Then I thought: let's reduce the memory consumption ! The code from problem 135 required about 200 MByte RAM. 28 | // I replaced the ''std::vector solutions'' by two bitfields ''atLeastOne'' and ''moreThanOne'': 29 | // - both have one bit per possible solution 30 | // - both are initialized with false 31 | // - if ''atLeastOne[current]'' is ''false'', then there was no solution so far ==> set it to ''true'' 32 | // - if ''atLeastOne[current]'' is ''true'', then there was at least one solution ==> set ''moreThanOne[current]'' to ''true'' 33 | // 34 | // The correct result is the number of all ''true'' entries in ''atLeastOne'' minus all ''true'' in ''moreThanOne''. 35 | // 36 | // Memory consumption is reduced to 1/16th ... or 14 MByte including I/O overhead etc. Execution time remained unchanged. 37 | 38 | #include 39 | #include 40 | 41 | int main() 42 | { 43 | const unsigned int limit = 50000000; 44 | // all bits set to zero 45 | std::vector atLeastOne (limit, false); 46 | std::vector moreThanOne(limit, false); 47 | 48 | for (unsigned int a = 1; a < limit; a++) 49 | for (auto b = (a + 3) / 4; b < a; b++) 50 | { 51 | auto current = a * (4*b - a); 52 | if (current >= limit) 53 | break; 54 | 55 | // already had a solution (or more) ? 56 | if (atLeastOne[current]) 57 | moreThanOne[current] = true; 58 | else 59 | // nope, first solution 60 | atLeastOne [current] = true; 61 | } 62 | 63 | // count all with exactly 1 solution 64 | unsigned int count = 0; 65 | for (unsigned int i = 0; i < limit; i++) 66 | if (atLeastOne[i] && !moreThanOne[i]) 67 | count++; 68 | 69 | std::cout << count << std::endl; 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /euler-0139.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Pythagorean tiles 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=139 7 | // http://euler.stephan-brumme.com/139/ 8 | // 9 | // # Problem 10 | // Let (a, b, c) represent the three sides of a right angle triangle with integral length sides. 11 | // It is possible to place four such triangles together to form a square with length c. 12 | // 13 | // ![square](p139.gif) 14 | // 15 | // For example, (3, 4, 5) triangles can be placed together to form a 5 by 5 square with a 1 by 1 hole in the middle 16 | // and it can be seen that the 5 by 5 square can be tiled with twenty-five 1 by 1 squares. 17 | // 18 | // However, if (5, 12, 13) triangles were used then the hole would measure 7 by 7 and these could not be used to tile the 13 by 13 square. 19 | // 20 | // Given that the perimeter of the right triangle is less than one-hundred million, how many Pythagorean triangles would allow such a tiling to take place? 21 | // 22 | // # Solved by 23 | // Stephan Brumme 24 | // June 2017 25 | // 26 | // # Algorithm 27 | // The sides of each triangle are `a <= b < c`. 28 | // In this picture shown above, `c` is the length of the "outer square" and `b - a` is the length of the "hole". 29 | // A tiling exists only if `c` is a multiple of `b - a`, that means ''c % (b - a) == 0''. 30 | // 31 | // For the (3,4,5) triangle: `c mod (b-a) = 5 mod (4-3) = 5 mod 1 = 0` ==> yes, tiling exists 32 | // For the (5,12,13) triangle: `c mod (b-a) = 13 mod (12-5) = 13 mod 7 = 6` ==> no 33 | // 34 | // I generate all basic Pythagorean triplets (see problem 75) and check if ''c % (b - a) == 0''. 35 | // Then all multiples create a valid tiling, too: `k * c mod (k * b - k * a) = k * c mod k * (b - a) = k * (c mod (b - a))` and if `x mod y = 0` then always `kx mod y = 0`. 36 | // There are `\lfloor dfrac{10^8}{a+b+c} \rfloor` valid multiples for each basic triplets. 37 | // 38 | // # Note 39 | // There is a subtle problem with the way basic triplets are generated: `a` and `b` are not always `a <= b` ... sometimes `a > b`. 40 | // So actually the correct test for a valid tiling is ''c % abs(b - a) == 0'' (that's what my ''diff'' variable is for). 41 | // 42 | // When I looked at the valid basic triplets then I saw that `b - a = 1` in all cases. There are actually only 10 basic triplets. 43 | 44 | #include 45 | 46 | // find greatest common divisor 47 | template 48 | T gcd(T a, T b) 49 | { 50 | while (a != 0) 51 | { 52 | T c = a; 53 | a = b % a; 54 | b = c; 55 | } 56 | return b; 57 | } 58 | 59 | int main() 60 | { 61 | unsigned int tests = 1; 62 | std::cin >> tests; 63 | while (tests--) 64 | { 65 | unsigned int maxLength = 100000000; 66 | std::cin >> maxLength; 67 | 68 | unsigned int numValid = 0; 69 | for (unsigned int m = 2; 2*m*m < maxLength; m++) 70 | for (unsigned int n = 1; n < m; n++) 71 | { 72 | // only valid m and n 73 | if ((m + n) % 2 != 1) 74 | continue; 75 | if (gcd(m, n) != 1) 76 | continue; 77 | 78 | // compute basic triplet 79 | auto a = m*m - n*n; 80 | auto b = 2*m*n; 81 | auto c = m*m + n*n; 82 | auto sum = a + b + c; 83 | 84 | // length of a side of the hole 85 | unsigned int diff = b - a; 86 | if (a > b) 87 | diff = a - b; 88 | 89 | // check if outer square is a multiple 90 | if (diff > 0 && c % diff == 0) 91 | { 92 | // number of valid triplets derived from the current basic triplet 93 | auto moreTriples = maxLength / sum; 94 | numValid += moreTriples; 95 | } 96 | } 97 | 98 | std::cout << numValid << std::endl; 99 | } 100 | 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /euler-0142.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Perfect Square Collection 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=142 7 | // http://euler.stephan-brumme.com/142/ 8 | // 9 | // # Problem 10 | // Find the smallest x + y + z with integers x > y > z > 0 such that x + y, x − y, x + z, x − z, y + z, y − z are all perfect squares. 11 | // 12 | // # Solved by 13 | // Stephan Brumme 14 | // June 2017 15 | // 16 | // # Algorithm 17 | // I have to solve six equations: 18 | // (1) `a^2 = x + y` 19 | // (2) `b^2 = x - y` 20 | // (3) `c^2 = x + z` 21 | // (4) `d^2 = x - z` 22 | // (5) `e^2 = y + z` 23 | // (6) `f^2 = y - z` 24 | // 25 | // And this condition has to be obeyed: 26 | // (7) `x > y > z > 0` 27 | // 28 | // If I add (1) and (2), then I have `x`: 29 | // (8) `a^2 + b^2 = 2x` ==> `x = frac{1}{2}(a^2 + b^2)` 30 | // 31 | // After reordering (1) I get the value of `y`: 32 | // (9) `y = a^2 - x` 33 | // 34 | // The same trick applied to (3): 35 | // (10) `z = c^2 - x` 36 | // 37 | // All equations can be solved if I find valid values for `a^2`, `b^2` and `c^2`. 38 | // However, when computing `d^2`, `e^2` and `f^2` based on (4), (5) and (6) then a few "fake" solutions appear where 39 | // `d^2`, `e^2` and `f^2` are not perfect squares. 40 | // 41 | // My program has three nested loops that iterate over possible values `a`, `b` and `c`. 42 | // A few optimizations are required to finish the algorithm in a reasonable amount of time: 43 | // - `x` must be an integer and from (8) follows that `a^2 + b^2` must be even, that means `a` and `b` are both odd or both even 44 | // - all numbers are positive therefore from (10) follows that `c^2 > x` which is the same as `c > sqrt{x}` 45 | // - instead of checking a number on-the-fly whether it is a perfect square, I precompute a small look-up table 46 | // 47 | // # Alternative 48 | // There are many faster solutions. My short program finishes in less than 0.1 seconds - that's why I don't care about more optimizations. 49 | 50 | #include 51 | #include 52 | #include 53 | 54 | int main() 55 | { 56 | // in my tests I found that all tested squares are well below one million 57 | const unsigned int Limit = 1000000; 58 | 59 | // record all square numbers 60 | // [n] => [true, if n is a perfect square] 61 | std::bitset isSquare; // default is false / zero 62 | for (unsigned int i = 1; i*i < isSquare.size(); i++) 63 | isSquare[i*i] = true; 64 | 65 | // substitute in (3): 66 | // (9) z = c^2 - x 67 | for (unsigned int a = 3; ; a++) 68 | { 69 | // a and b must be both odd or both even 70 | unsigned int minB = (a % 2 == 0) ? 2 : 1; 71 | for (unsigned int b = minB; b < a; b += 2) // keep parity, skip every second number 72 | { 73 | // from (8): compute x 74 | auto x = (a*a + b*b) / 2; 75 | // from (9): compute y 76 | auto y = a*a - x; 77 | // ensure x > y 78 | if (x <= y) 79 | break; 80 | 81 | for (unsigned int c = (unsigned int)sqrt(x) + 1; ; c++) 82 | { 83 | // from (10): compute z 84 | auto z = c*c - x; 85 | // ensure y > z 86 | if (y <= z) 87 | break; 88 | 89 | // check whether d^2, e^2 and f^2 are perfect squares 90 | if (isSquare[x - z] && 91 | isSquare[y + z] && 92 | isSquare[y - z]) 93 | { 94 | // found a solution, stop program 95 | std::cout << x + y + z << std::endl; 96 | return 0; 97 | } 98 | } 99 | } 100 | } 101 | 102 | // never reached 103 | } 104 | -------------------------------------------------------------------------------- /euler-0145.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // How many reversible numbers are there below one-billion? 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=145 7 | // http://euler.stephan-brumme.com/145/ 8 | // 9 | // # Problem 10 | // Some positive integers n have the property that the sum `n + reverse(n)` consists entirely of odd (decimal) digits. 11 | // For instance, 36 + 63 = 99 and 409 + 904 = 1313. We will call such numbers reversible; so 36, 63, 409, and 904 are reversible. 12 | // Leading zeroes are not allowed in either `n` or `reverse(n)`. 13 | // 14 | // There are 120 reversible numbers below one-thousand. 15 | // 16 | // How many reversible numbers are there below one-billion (`10^9`)? 17 | // 18 | // # Solved by 19 | // Stephan Brumme 20 | // May 2017 21 | // 22 | // # Algorithm 23 | // A simple and straightforward brute force solution - and it finishes in less than a second. 24 | // I'm pretty sure there is a smarter approach but from time to time you need to unleash the raw power of modern CPUs ... 25 | // 26 | // Actually, I have added two important optimization: 27 | // - there are no solutions between `10^8` and `10^9` ==> makes the program 10x faster 28 | // - either the first or the last digit must be odd ==> assume the last is odd and multiply result by 2 ==> 2x faster 29 | 30 | #include 31 | #include 32 | 33 | 34 | // note: my code only reversed odd numbers, they can't produce a leading zero 35 | unsigned int reverse(unsigned int x) 36 | { 37 | unsigned int result = 0; 38 | while (x > 9) // speed optimization: skip the last digit 39 | { 40 | auto digit = x % 10; 41 | result *= 10; 42 | result += digit; 43 | x /= 10; 44 | } 45 | // simple processing of the last digit, saves one division/modulo ;-) 46 | return result * 10 + x; 47 | } 48 | 49 | // return true if all digits are odd 50 | bool onlyOdd(unsigned int x) 51 | { 52 | while (x > 0) 53 | { 54 | // found an even digit ? 55 | if (x % 2 == 0) 56 | return false; 57 | x /= 10; 58 | } 59 | // yes, all odd 60 | return true; 61 | } 62 | 63 | int main() 64 | { 65 | // if the first digit is odd, then the last has to be even 66 | // the same logic applies in reverse order, too 67 | // therefore analyze only odd numbers and multiply the result by 2 68 | const unsigned int factor = 2; 69 | 70 | unsigned int count = 0; 71 | // no solutions between 10^8 and 10^9 72 | for (unsigned int i = 11; i < 100*1000*1000; i += factor) 73 | if (onlyOdd(i + reverse(i))) 74 | count += factor; 75 | 76 | std::cout << count << std::endl; 77 | return 0; 78 | } 79 | 80 | -------------------------------------------------------------------------------- /euler-0164.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Numbers for which no three consecutive digits have a sum greater than a given value 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=164 7 | // http://euler.stephan-brumme.com/164/ 8 | // 9 | // # Problem 10 | // How many 20 digit numbers n (without any leading zero) exist such that no three consecutive digits of n have a sum greater than 9? 11 | // 12 | // # Solved by 13 | // Stephan Brumme 14 | // June 2017 15 | // 16 | // # Algorithm 17 | // A straight-forward recursive solution: 18 | // - start with an "empty" number (no digits at all) 19 | // - append a digit (0 to 9) if the previous two digits and the current digits don't exceed 9 20 | // - stop if enough digits where appended (''digits = 0'') 21 | // 22 | // A substantial number of calls will have the same parameter set. A small ''cache'' prevents re-computing the same results over and over again. 23 | // 24 | // # Hackerrank 25 | // There can be up to 100 digits. 26 | // 27 | // # Note 28 | // You can change the maximum sum of three consecutive digits, too (default is 9). 29 | 30 | #include 31 | 32 | #define ORIGINAL 33 | 34 | // Hackerrank: up to 100 digits 35 | // Project Euler: 20 digits 36 | const unsigned int MaxDigits = 100; 37 | 38 | // bonus feature: change maximum sum of three consecutive digits 39 | unsigned int maxSum = 9; 40 | 41 | // count matching numbers 42 | // prevprev: the digit two positions to the left of the current digit 43 | // prev : the digit one position to the left of the current digit 44 | // digits : number of remainings digits 45 | // isFirst : true only for the first digit (which must not be zero) 46 | unsigned long long search(unsigned int prevprev, unsigned int prev, unsigned int digits, bool isFirst) 47 | { 48 | // done ? 49 | if (digits == 0) 50 | return 1; 51 | 52 | // memoize 53 | unsigned int id = digits * 100 + prevprev * 10 + prev; // simple hash 54 | static unsigned long long cache[(MaxDigits + 1) * 100] = { 0 }; 55 | if (cache[id] != 0) 56 | return cache[id]; 57 | 58 | // iterate over all digits such that current + prev + prevprev <= 9 59 | unsigned long long result = 0; 60 | for (unsigned int current = 0; current + prev + prevprev <= maxSum; current++) 61 | { 62 | // no leading zero 63 | if (current == 0 && isFirst) 64 | continue; 65 | 66 | // add next digit 67 | result += search(prev, current, digits - 1, false); 68 | } 69 | 70 | #ifndef ORIGINAL 71 | // Hackerrank only 72 | result %= 1000000007; 73 | #endif 74 | 75 | // memoize 76 | cache[id] = result; 77 | return result; 78 | } 79 | 80 | int main() 81 | { 82 | unsigned int digits = 20; 83 | std::cin >> digits; 84 | if (digits > MaxDigits) 85 | return 1; 86 | 87 | #ifdef ORIGINAL 88 | // bonus feature: change maximum sum of three consecutive digits 89 | std::cin >> maxSum; 90 | #endif 91 | 92 | std::cout << search(0, 0, digits, true) << std::endl; 93 | 94 | return 0; 95 | } 96 | -------------------------------------------------------------------------------- /euler-0173.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Using up to one million tiles how many different "hollow" square laminae can be formed? 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=173 7 | // http://euler.stephan-brumme.com/173/ 8 | // 9 | // # Problem 10 | // We shall define a square lamina to be a square outline with a square "hole" so that the shape possesses vertical and horizontal symmetry. 11 | // For example, using exactly thirty-two square tiles we can form two different square laminae: 12 | // 13 | // ![tiles](p173_square_laminas.gif) 14 | // 15 | // With one-hundred tiles, and not necessarily using all of the tiles at one time, it is possible to form forty-one different square laminae. 16 | // 17 | // Using up to one million tiles how many different square laminae can be formed? 18 | // 19 | // # Solved by 20 | // Stephan Brumme 21 | // May 2017 22 | // 23 | // # Algorithm 24 | // Each tiling consists of multiple "rings". The first example has two rings, the second only one. 25 | // For each ring with side/edge length `x` we need `4(x-1)` tiles. 26 | // 27 | // My program iterates over all possible rings and tries to insert as many smaller rings as possible until one million is exceeded. 28 | // The smallest ring has an edge length of 3 tiles. A ring inside another ring has an edge length which is 2 tiles shorter. 29 | // 30 | // # Hackerrank 31 | // My brute-force approach solves the original problem in less than 0.01 seconds but can't solve situations with more than `10^9` tiles in a reasonable time. 32 | 33 | #include 34 | 35 | int main() 36 | { 37 | unsigned int limit = 1000000; 38 | std::cin >> limit; 39 | 40 | // result 41 | unsigned int count = 0; 42 | 43 | // start with smallest outer ring 44 | for (unsigned int outer = 3; ; outer++) 45 | { 46 | unsigned int sum = 0; 47 | // add as many inner rings as possible 48 | for (unsigned int inner = outer; inner >= 3; inner -= 2) 49 | { 50 | // tiles needed to create one ring whose sides are "inner" tiles long 51 | unsigned int ring = 4 * (inner - 1); 52 | 53 | // runnng out of tiles ? 54 | if (sum + ring > limit) 55 | break; 56 | 57 | // add valid ring 58 | sum += ring; 59 | count++; 60 | } 61 | 62 | // no more inner rings possible, abort 63 | if (sum == 0) 64 | break; 65 | } 66 | 67 | std::cout << count << std::endl; 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /euler-0174.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Counting the number of "hollow" square laminae that can form one, two, three, ... distinct arrangements 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=174 7 | // http://euler.stephan-brumme.com/174/ 8 | // 9 | // # Problem 10 | // We shall define a square lamina to be a square outline with a square "hole" so that the shape possesses vertical and horizontal symmetry. 11 | // 12 | // Given eight tiles it is possible to form a lamina in only one way: 3x3 square with a 1x1 hole in the middle. 13 | // However, using thirty-two tiles it is possible to form two distinct laminae. 14 | // 15 | // ![tiles](https://projecteuler.net/project/images/p173_square_laminas.gif) 16 | // 17 | // If `t` represents the number of tiles used, we shall say that `t = 8` is type `L(1)` and `t = 32` is type `L(2)`. 18 | // 19 | // Let `N(n)` be the number of `t <= 1000000` such that `t` is type `L(n)`; for example, `N(15) = 832`. 20 | // 21 | // What is `sum{N(n)}` for `1 <= n <= 10`? 22 | // 23 | // # Solved by 24 | // Stephan Brumme 25 | // May 2017 26 | // 27 | // # Algorithm 28 | // I copied most of my solution from the previous problem (problem 173). 29 | // A second pass iterates over all solutions and counts which number of tiles has between 1 and 10 solutions. This information is stored in ''result''. 30 | // Then we just have to look up the relevant element, e.g. ''result[1000000]'' for the original problem. 31 | // 32 | // # Hackerrank 33 | // I could have written my solution without the ''result'' array because only ''result[1000000]'' was relevant. 34 | // However, Hackerrank queries thousands of other elements from ''result''. 35 | // Due to heavy I/O processing, which is kind of slow in C++, I barely solve the second test case. 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | int main() 42 | { 43 | const unsigned int limit = 1000000; 44 | 45 | // count different layouts for a number of tiles 46 | std::vector solutions(limit + 1, 0); 47 | 48 | // start with smallest outer ring 49 | for (unsigned int outer = 3; ; outer++) 50 | { 51 | unsigned int sum = 0; 52 | // add as many inner rings as possible 53 | for (unsigned int inner = outer; inner >= 3; inner -= 2) 54 | { 55 | // tiles needed to create one ring whose sides are "inner" tiles long 56 | unsigned int ring = 4 * (inner - 1); 57 | 58 | // runnng out of tiles ? 59 | if (sum + ring > limit) 60 | break; 61 | 62 | // add valid ring 63 | sum += ring; 64 | solutions[sum]++; 65 | } 66 | 67 | // no more inner rings possible, abort 68 | if (sum == 0) 69 | break; 70 | } 71 | 72 | // pre-process all possible answers 73 | std::vector result(solutions.size()); 74 | unsigned int one2ten = 0; 75 | for (unsigned int i = 0; i < solutions.size(); i++) 76 | { 77 | auto s = solutions[i]; 78 | if (s >= 1 && s <= 10) 79 | one2ten++; 80 | 81 | result[i] = one2ten; 82 | } 83 | 84 | // process test cases 85 | unsigned int tests; 86 | std::cin >> tests; 87 | while (tests--) 88 | { 89 | unsigned int last = limit; 90 | std::cin >> last; 91 | // simple lookup 92 | std::cout << result[last] << std::endl; 93 | } 94 | 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /euler-0179.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Consecutive positive divisors 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=179 7 | // http://euler.stephan-brumme.com/179/ 8 | // 9 | // # Problem 10 | // Find the number of integers `1 < n < 10^7`, for which `n` and `n + 1` have the same number of positive divisors. 11 | // For example, 14 has the positive divisors 1, 2, 7, 14 while 15 has 1, 3, 5, 15. 12 | // 13 | // # Solved by 14 | // Stephan Brumme 15 | // May 2017 16 | // 17 | // # Algorithm 18 | // Finally a simple problem ... I create an array ''divisors'' with `10^7` entries. 19 | // Two nested loops go through all pairs `(i,k)` where `i * k < 10^7` and increment each entry at ''divisors[i * k]'' (in my code ''j = i * k''). 20 | // 21 | // A second pass counts how often ''divisors[n] == divisors[n + 1]''. 22 | // 23 | // # Note 24 | // 8648640 has the most divisors: 447. 25 | // 26 | // A ''short'' uses less memory than an ''int'' which caused less memory stalls (while still being able to store that maximum value of 447). 27 | // I saw a 20% performance boost on my system when switching from ''int'' to ''short''. 28 | // 29 | // Each number is divisible by 1 and by itself. When excluding those two divisors I will still find the correct solution. 30 | // However, the program didn't become faster when starting the outer loop at ''2'' (instead of ''1'') and the inner loop at ''2*i'' (instead of ''i''). 31 | 32 | #include 33 | #include 34 | 35 | #define ORIGINAL 36 | 37 | int main() 38 | { 39 | // almost like a reverse prime sieve ... 40 | unsigned int limit = 10000000; 41 | #ifdef ORIGINAL 42 | std::cin >> limit; 43 | #endif 44 | 45 | // count divisors of the number immediately after "limit", too 46 | limit++; 47 | 48 | // will have the number of divisors for each number 49 | std::vector divisors(limit, 0); 50 | 51 | // all numbers which can be a divisor ... 52 | for (unsigned int i = 1; i <= limit / 2; i++) 53 | // and all of their multiples 54 | for (unsigned int j = i; j <= limit; j += i) 55 | divisors[j]++; 56 | 57 | #ifdef ORIGINAL 58 | unsigned int result = 0; 59 | for (unsigned int i = 2; i < limit; i++) 60 | if (divisors[i] == divisors[i + 1]) 61 | result++; 62 | std::cout << result << std::endl; 63 | #else 64 | // [index] => [numbers up to index which match the "neighbor" condition] 65 | std::vector count(limit + 1, 0); 66 | // count numbers whose bigger neighbors has the same number of divisors 67 | for (unsigned int i = 2; i < limit; i++) 68 | { 69 | count[i] = count[i - 1]; 70 | if (divisors[i] == divisors[i + 1]) 71 | count[i]++; 72 | } 73 | 74 | // simple lookup of results 75 | unsigned int tests = 1; 76 | std::cin >> tests; 77 | while (tests--) 78 | { 79 | unsigned int index; 80 | std::cin >> index; 81 | std::cout << count[index - 1] << std::endl; 82 | } 83 | #endif 84 | 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /euler-0181.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Investigating in how many ways objects of two different colours can be grouped 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=181 7 | // http://euler.stephan-brumme.com/181/ 8 | // 9 | // # Problem 10 | // Having three black objects B and one white object W they can be grouped in 7 ways like this: 11 | // (BBBW), (B,BBW), (B,B,BW), (B,B,B,W), (B,BB,W), (BBB,W), (BB,BW) 12 | // 13 | // In how many ways can sixty black objects B and forty white objects W be thus grouped? 14 | // 15 | // # Solved by 16 | // Stephan Brumme 17 | // June 2017 18 | // 19 | // # Algorithm 20 | // My solution is somehow similar to the coin-change algorithm: 21 | // - each group can be treated as a sequence of black and white objects, BWBW is the same as BBWW 22 | // - all groups can be sorted by their size and, if multiple groups have the same size, by their lexicographical order 23 | // 24 | // For ''maxBlack = 3'' and ''maxWhite = 1'' these groups exist: 25 | // (B,B,B,W), (B,B,BW), (B,W,BB), (B, BBW), (W, BBB), (BB, BW), (BBBW) 26 | // These are exactly the same as in the problem statement but in a different order. 27 | // 28 | // Two outer loops iterate over all possible sequences of black and white objects. 29 | // The inner loops place them at every possible positions (until the number of available objects is exhausted). 30 | // 31 | // The result will be found in ''current[60][40]''. 32 | // 33 | // # Alternative 34 | // You can solve this problem with Dynamic Programming, too. 35 | // I wrote a simple prototype but it turned out to be much slower (8 seconds vs. 0.04 seconds). 36 | 37 | #include 38 | 39 | // limits 40 | const unsigned int MaxBlack = 160; 41 | const unsigned int MaxWhite = 160; 42 | const unsigned int Modulo = 1000000007; // Hackerrank only 43 | 44 | int main() 45 | { 46 | #define ORIGINAL 47 | #ifndef ORIGINAL 48 | unsigned int tests = 1; 49 | std::cin >> tests; 50 | while (tests--) 51 | #endif 52 | { 53 | unsigned int maxBlack = MaxBlack; 54 | unsigned int maxWhite = MaxWhite; 55 | std::cin >> maxBlack >> maxWhite; 56 | 57 | // static array size: actually it would be sufficient to use maxBlack instead of MaxBlack 58 | // (and maxWhite instead of MaxWhite) 59 | unsigned long long previous[MaxBlack + 1][MaxWhite + 1]; 60 | unsigned long long current [MaxBlack + 1][MaxWhite + 1]; 61 | 62 | // initialize 63 | for (unsigned int i = 0; i <= maxBlack; i++) 64 | for (unsigned int j = 0; j <= maxWhite; j++) 65 | previous[i][j] = 0; 66 | previous[0][0] = 1; 67 | 68 | // all possible subsets 69 | for (unsigned int useBlack = 0; useBlack <= maxBlack; useBlack++) 70 | for (unsigned int useWhite = 0; useWhite <= maxWhite; useWhite++) 71 | { 72 | // skip empty subset 73 | if (useBlack == 0 && useWhite == 0) 74 | continue; 75 | 76 | // put subset at every possible position 77 | for (unsigned int i = 0; i <= maxBlack; i++) 78 | for (unsigned int j = 0; j <= maxWhite; j++) 79 | { 80 | current[i][j] = 0; 81 | 82 | // place it repeatedly 83 | unsigned int k = 0; 84 | while (i >= k * useBlack && j >= k * useWhite) 85 | { 86 | current[i][j] += previous[i - k * useBlack][j - k * useWhite]; 87 | k++; 88 | } 89 | #ifndef ORIGINAL 90 | current[i][j] %= Modulo; 91 | #endif 92 | } 93 | 94 | // copy for next iteration 95 | for (unsigned int i = 0; i <= maxBlack; i++) 96 | for (unsigned int j = 0; j <= maxWhite; j++) 97 | previous[i][j] = current[i][j]; 98 | } 99 | 100 | // print result 101 | std::cout << current[maxBlack][maxWhite] << std::endl; 102 | } 103 | 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /euler-0183.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Maximum product of parts 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=183 7 | // http://euler.stephan-brumme.com/183/ 8 | // 9 | // # Problem 10 | // Let `N` be a positive integer and let `N` be split into `k` equal parts, `r = N/k`, so that `N = r + r + ... + r`. 11 | // Let `P` be the product of these parts, `P = r * r * ... * r = r^k`. 12 | // 13 | // For example, if 11 is split into five equal parts, `11 = 2.2 + 2.2 + 2.2 + 2.2 + 2.2`, then `P = 2.2^5 = 51.53632`. 14 | // 15 | // Let `M(N) = P_max` for a given value of `N`. 16 | // 17 | // It turns out that the maximum for `N = 11` is found by splitting eleven into four equal parts which leads to `P_max = (11/4)^4`; 18 | // that is, `M(11) = 14641/256 = 57.19140625`, which is a terminating decimal. 19 | // 20 | // However, for `N = 8` the maximum is achieved by splitting it into three equal parts, so `M(8) = 512/27`, which is a non-terminating decimal. 21 | // 22 | // Let `D(N) = N` if `M(N)` is a non-terminating decimal and `D(N) = -N` if `M(N)` is a terminating decimal. 23 | // 24 | // For example, `sum{D(N)}` for `5 <= N <= 100` is 2438. 25 | // 26 | // Find `sum{D(N)}` for `5 <= N <= 10000`. 27 | // 28 | // # Solved by 29 | // Stephan Brumme 30 | // June 2017 31 | // 32 | // # Algorithm 33 | // My first approach was to have a simple loop running from k = 1 to n: 34 | // - find the largest `(n/k)^k` 35 | // - figure out whether `(n/k)^k` terminates 36 | // 37 | // When I looked at the values of `k` I saw that `n/k` was always ` approx 2.7`. 38 | // And Wolfram Alpha confirmed my suspicion: http://www.wolframalpha.com/input/?i=max((8%2Fn)%5En) 39 | // `M(8) = max((8/n)^n) = e^{8/e}` at `k = 8/e` where `e = 2.7182818284...`, see https://en.wikipedia.org/wiki/E_(mathematical_constant) 40 | // 41 | // In general: `max((x/n)^n) = e^{n/e}` at `k = n/e` 42 | // Unfortunately, `n/e` isn't an integer and therefore the best `k` is ''k = round(n / 2.718281828)'' (that's enough digits of `e` for this problem) 43 | // 44 | // The number `(n/k)^k` terminates if `n/k` terminates. 45 | // And `n/k` terminates if the greatest common divisor `gcd(n, k)` has only 2 and 5 as prime factors (something I learnt in problem 26). 46 | // 47 | // # Alternative 48 | // As mentioned before, my initial approach computed all `(n/k)^k`. 49 | // But numbers became huge very fast ... well, I didn't need their "true" value: it's sufficient to have their logarithm because if `a < b` then `log(a) < log(b)`, too. 50 | // In the end I converted `(x/n)^n` to `n log(x/n)`. 51 | // 52 | // Using ''round'' can be dangerous if not enough digits of `e` are used. 10 digits are totally fine for that problem, though. 53 | // 54 | // # Hackerrank 55 | // I need to cache intermediate result to be able to handle the huge number of input values. 56 | 57 | #include 58 | #include 59 | #include 60 | 61 | int main() 62 | { 63 | // five dummy entries 64 | std::vector cache(5, 0); 65 | 66 | #define ORIGINAL 67 | #ifndef ORIGINAL 68 | unsigned int tests = 1; 69 | std::cin >> tests; 70 | while (tests--) 71 | #endif 72 | { 73 | unsigned int limit = 10000; 74 | std::cin >> limit; 75 | 76 | auto result = cache.back(); 77 | for (unsigned int n = cache.size(); n <= limit; n++) 78 | { 79 | unsigned int k = round(n / 2.718281828); 80 | 81 | // terminating only if n/k has only prime factors 2 and 5 82 | while (k % 5 == 0) 83 | k /= 5; 84 | while (k % 2 == 0) 85 | k /= 2; 86 | 87 | if (n % k == 0) 88 | result -= n; 89 | else 90 | result += n; 91 | 92 | // cache intermediate results, too (needed for Hackerrank only) 93 | cache.push_back(result); 94 | } 95 | 96 | // display result 97 | std::cout << cache[limit] << std::endl; 98 | } 99 | 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /euler-0187.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Semiprimes 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=187 7 | // http://euler.stephan-brumme.com/187/ 8 | // 9 | // # Problem 10 | // A composite is a number containing at least two prime factors. For example, `15 = 3 * 5`; `9 = 3 * 3`; `12 = 2 * 2 * 3`. 11 | // 12 | // There are ten composites below thirty containing precisely two, not necessarily distinct, prime factors: 4, 6, 9, 10, 14, 15, 21, 22, 25, 26. 13 | // 14 | // How many composite integers, `n < 10^8`, have precisely two, not necessarily distinct, prime factors? 15 | // 16 | // # Solved by 17 | // Stephan Brumme 18 | // May 2017 19 | // 20 | // # Algorithm 21 | // My fast [prime sieve](../toolbox/#primesieve-eratosthenes) generates all prime numbers below `5 * 10^7` in about 120ms. 22 | // Then all primes numbers are pairwise multiplied. I count the number of all products below `10^8`. 23 | // 24 | // # Alternative 25 | // A prime counting function can solve this almost instantly (see my solution for problem 501). 26 | // 27 | // Or even simpler: ''prime[j]'' is the smallest prime to be multiplied with ''prime[i]''. 28 | // Then ''limit / prime[i]'' will be the maximum number for ''prime[j]''. A simple binary search in ''primes'' can count how many primes are relevant. 29 | // (that's prime counting, too, and equivalent to the speed-up trick in problem 501 for small ''n''). 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | // ---------- standard prime sieve from my toolbox ---------- 36 | 37 | // odd prime numbers are marked as "true" in a bitvector 38 | std::vector sieve; 39 | 40 | // return true, if x is a prime number 41 | bool isPrime(unsigned int x) 42 | { 43 | // handle even numbers 44 | if ((x & 1) == 0) 45 | return x == 2; 46 | 47 | // lookup for odd numbers 48 | return sieve[x >> 1]; 49 | } 50 | 51 | // find all prime numbers from 2 to size 52 | void fillSieve(unsigned int size) 53 | { 54 | // store only odd numbers 55 | const unsigned int half = size >> 1; 56 | 57 | // allocate memory 58 | sieve.resize(half, true); 59 | // 1 is not a prime number 60 | sieve[0] = false; 61 | 62 | // process all relevant prime factors 63 | for (unsigned int i = 1; 2*i*i < half; i++) 64 | // do we have a prime factor ? 65 | if (sieve[i]) 66 | { 67 | // mark all its multiples as false 68 | unsigned int current = 3*i+1; 69 | while (current < half) 70 | { 71 | sieve[current] = false; 72 | current += 2*i+1; 73 | } 74 | } 75 | } 76 | 77 | // ---------- and now problem-specific code ---------- 78 | 79 | int main() 80 | { 81 | // generate all primes 82 | unsigned int limit = 100000000; 83 | unsigned int largestPrime = limit / 2 + 100; // at least one more prime than strictly needed 84 | fillSieve(largestPrime); 85 | 86 | // extract all prime numbers from sieve 87 | std::vector primes = { 2 }; 88 | primes.reserve(3002000); // avoid frequent re-allocations 89 | for (unsigned int i = 3; i < largestPrime; i += 2) 90 | if (isPrime(i)) 91 | primes.push_back(i); 92 | 93 | #define ORIGINAL 94 | #ifndef ORIGINAL 95 | // Hackerrank has several test cases 96 | unsigned int tests = 1; 97 | std::cin >> tests; 98 | while (tests--) 99 | #endif 100 | { 101 | std::cin >> limit; 102 | 103 | // compute all products of primes i and j where i <= j 104 | unsigned int count = 0; 105 | for (unsigned int i = 0; primes[i] * primes[i] < limit; i++) 106 | for (unsigned int j = i; primes[i] * primes[j] < limit; j++) 107 | // found one more solutions ... 108 | count++; 109 | 110 | std::cout << count << std::endl; 111 | } 112 | 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /euler-0188.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // The hyperexponentiation of a number 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=188 7 | // http://euler.stephan-brumme.com/188/ 8 | // 9 | // # Problem 10 | // The hyperexponentiation or tetration of a number `a` by a positive integer `b`, denoted by `a \upuparrows b` or `{^b}a`, is recursively defined by: 11 | // 12 | // `a \upuparrows 1 = a`, 13 | // `a \upuparrows (k+1) = a(a \upuparrows k)`. 14 | // 15 | // Thus we have e.g. `3 \upuparrows 2 = 3^3 = 27`, hence `3 \upuparrows 3 = 3^27 = 7625597484987` and `3 \upuparrows 4` is roughly `10^{3.6383346400240996 * 10^12}`. 16 | // 17 | // Find the last 8 digits of `1777 \upuparrows 1855`. 18 | // 19 | // # Solved by 20 | // Stephan Brumme 21 | // June 2017 22 | // 23 | // # Algorithm 24 | // ''powmod'' was taken from my [toolbox](../toolbox/). 25 | // 26 | // When I printed intermediate results of ''tetration'' I found that the last digits converge pretty quickly. 27 | // But even without the early-exit optimization the code finishes almost instantly. 28 | 29 | #include 30 | 31 | // return (base^exponent) % modulo for 32-bit values, no need for mulmod 32 | unsigned int powmod(unsigned int base, unsigned int exponent, unsigned int modulo) 33 | { 34 | unsigned int result = 1; 35 | while (exponent > 0) 36 | { 37 | // fast exponentation: 38 | // odd exponent ? a^b = a*a^(b-1) 39 | if (exponent & 1) 40 | result = (result * (unsigned long long)base) % modulo; 41 | 42 | // even exponent ? a^b = (a*a)^(b/2) 43 | base = (base * (unsigned long long)base) % modulo; 44 | exponent >>= 1; 45 | } 46 | return result; 47 | } 48 | 49 | // compute result 50 | unsigned int tetration(unsigned int a, unsigned int b, unsigned int modulo) 51 | { 52 | unsigned int last = 0; 53 | unsigned int result = 1; 54 | while (b--) 55 | { 56 | result = powmod(a, result, modulo); 57 | 58 | // converges pretty fast, abort early 59 | if (last == result) 60 | break; 61 | last = result; 62 | } 63 | return result; 64 | } 65 | 66 | int main() 67 | { 68 | unsigned int a = 1777; 69 | unsigned int b = 1855; 70 | std::cin >> a >> b; 71 | 72 | unsigned int modulo = 100000000; 73 | 74 | // abort if gcd(a, modulo) != 1 75 | if (a % 10 == 0) 76 | return 1; 77 | 78 | std::cout << tetration(a, b, modulo) << std::endl; 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /euler-0191.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Prize Strings 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=191 7 | // http://euler.stephan-brumme.com/191/ 8 | // 9 | // # Problem 10 | // A particular school offers cash rewards to children with good attendance and punctuality. 11 | // If they are absent for three consecutive days or late on more than one occasion then they forfeit their prize. 12 | // 13 | // During an n-day period a trinary string is formed for each child consisting of L's (late), O's (on time), and A's (absent). 14 | // 15 | // Although there are eighty-one trinary strings for a 4-day period that can be formed, exactly forty-three strings would lead to a prize: 16 | // 17 | // OOOO OOOA OOOL OOAO OOAA OOAL OOLO OOLA OAOO OAOA 18 | // OAOL OAAO OAAL OALO OALA OLOO OLOA OLAO OLAA AOOO 19 | // AOOA AOOL AOAO AOAA AOAL AOLO AOLA AAOO AAOA AAOL 20 | // AALO AALA ALOO ALOA ALAO ALAA LOOO LOOA LOAO LOAA 21 | // LAOO LAOA LAAO 22 | // 23 | // How many "prize" strings exist over a 30-day period? 24 | // 25 | // # Solved by 26 | // Stephan Brumme 27 | // May 2017 28 | // 29 | // # Algorithm 30 | // Another dynamic programming problem ... my function ''count'' has 3 parameters: 31 | // - ''day'' stands for the number of days to be evaluated, initially 30 32 | // - ''absent'' counts the consecutive absent days 33 | // - ''late'' represents the total number of days where the pupil was late 34 | // 35 | // There are two important things: 36 | // 1. ''absent'' has to be reset to zero everytime the pupil shows up (it doesn't matter whether on time or late) 37 | // 2. A massive amount of situations produce the same parameter set. That means, some parameter sets are evaluated several thousand times. 38 | // 39 | // A simple memoization scheme brings down the computation time from several seconds to less than 10 milliseconds: 40 | // There are at most 30*2*3 = 1800 different parameter sets: 41 | // - 30 days 42 | // - child was 0 or 1 days late so far 43 | // - he/she was 0, 1 or 2 days absent (only counting the most recent days) 44 | // 45 | // A simple hash ''days * 2 * 3 + absent * 2 + late'' is unique for each parameter set and used as a index for a small ''cache''. 46 | // 47 | // # Note 48 | // My cache can hold the results for up to 80 days. 49 | // The result fits in ''unsigned int'' for 30 days, too. 50 | 51 | #include 52 | 53 | // memoize intermediate results 54 | unsigned long long cache[80*2*3] = { 0 }; 55 | 56 | // recursively evaluate a day: 57 | // days - number of days left 58 | // absent - number of consecutive absent day (only consider up to three past days) 59 | // late - total number of late days 60 | unsigned long long count(unsigned int days, unsigned int absent = 0, unsigned int late = 0) 61 | { 62 | // too many consecutive absent days ? 63 | if (absent == 3) 64 | return 0; 65 | // too late to often ? 66 | if (late > 1) 67 | return 0; 68 | 69 | // all days passed ? => collect prize 70 | if (days == 0) 71 | return 1; 72 | 73 | // unique ID of current parameter set 74 | unsigned int hash = days * 2 * 3 + absent * 2 + late; 75 | // already computed ? 76 | if (cache[hash] != 0) 77 | return cache[hash]; 78 | 79 | unsigned long long result; 80 | // assume pupil is today neither late nor absent 81 | result = count(days - 1, 0, late); 82 | // assume pupil is absent today 83 | result += count(days - 1, absent + 1, late); 84 | // assume pupil is late today 85 | result += count(days - 1, 0, late + 1); 86 | 87 | // store result 88 | cache[hash] = result; 89 | return result; 90 | } 91 | 92 | int main() 93 | { 94 | unsigned int days; 95 | std::cin >> days; 96 | std::cout << count(days) << std::endl; 97 | return 0; 98 | } 99 | -------------------------------------------------------------------------------- /euler-0193.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Squarefree Numbers 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=193 7 | // http://euler.stephan-brumme.com/193/ 8 | // 9 | // # Problem 10 | // A positive integer `n` is called squarefree, if no square of a prime divides `n`, thus 1, 2, 3, 5, 6, 7, 10, 11 are squarefree, but not 4, 8, 9, 12. 11 | // 12 | // How many squarefree numbers are there below `2^50`? 13 | // 14 | // # Solved by 15 | // Stephan Brumme 16 | // June 2017 17 | // 18 | // # Algorithm 19 | // My program counts all non-squarefree numbers and then displays `2^50 - notSquarefree`. 20 | // 21 | // Any number can be written as a product of its prime factors: 22 | // `x = {p_1}^{e_1} * {p_2}^{e_2} * ... * {p_n}^{e_n}` 23 | // If `x` is squarefree, then all its exponents are `e_1 = e_2 = ... = e_n = 1`. 24 | // 25 | // A non-squarefree number, let's call it "squary", has at least one exponent `e_i > 1`. 26 | // The largest prime factor to be considered for finding squaries must be `{p_i}^2 < 2^50` or `p_i < sqrt{2^50}`. 27 | // 28 | // The first step in my program is to count the number of distinct prime factors for all numbers below `sqrt{2^50}` (these numbers are my "base numbers"). 29 | // The idea is that all multiples `k * b^2` of these "base numbers" `b` aren't squarefree. 30 | // However, all relevant "base number" must be squarefree themselves. That's why I track all "squary base numbers" in my ''ignore'' array. 31 | // 32 | // The number of multiples `k * b^2` of a "squary base number" ''i'' is ''numMultiples = limit / (b * b)''. 33 | // 34 | // There is one more problem - some numbers are counted multiple times. 35 | // For example `192 = 2^2 * 7^2` is a multiple of 2, 7 and 14 (=2*7). 36 | // A pretty sweet workaround solves this problem: 37 | // - if the number of prime factors of a base number is odd, then add the number of multiples 38 | // - if the number of prime factors of a base number is even, then the number of multiples was already added twice: once for each pair of prime factors 39 | // ==> in that case, subtract it 40 | 41 | #include 42 | #include 43 | #include 44 | 45 | int main() 46 | { 47 | unsigned long long limit = 1ULL << 50; 48 | std::cin >> limit; 49 | 50 | // largest prime factor that may appear as a square 51 | unsigned long long root = (unsigned long long)sqrt(limit); 52 | 53 | // count number of distinct prime factors 54 | std::vector numPrimeFactors(root, 0); 55 | // does any prime factor occurs multiple times ? 56 | std::vector ignore(root, false); 57 | for (unsigned long long prime = 2; prime < root; prime++) 58 | { 59 | // skip if not a prime number 60 | if (numPrimeFactors[prime] != 0) 61 | continue; 62 | 63 | // add the prime factor to all multiples 64 | for (auto j = prime; j < root; j += prime) 65 | numPrimeFactors[j]++; 66 | 67 | // all multiples have at least one prime factor multiples times, mark as invalid 68 | auto square = prime * prime; 69 | for (auto j = square; j < root; j += square) 70 | ignore[j] = true; 71 | } 72 | 73 | // count all numbers that are not squarefree 74 | unsigned long long notSquarefree = 0; 75 | for (unsigned long long base = 2; base < root; base++) 76 | { 77 | // at least one prime factor occurs multiple times ? 78 | if (ignore[base]) 79 | continue; 80 | 81 | // all multiples are not squarefree 82 | auto square = base * base; 83 | auto numMultiples = limit / square; 84 | 85 | // if the number of prime factors is odd, then these multiples are new 86 | if (numPrimeFactors[base] % 2 == 1) 87 | notSquarefree += numMultiples; 88 | else // else: when even number of prime factors, then we have seen these numbers before 89 | notSquarefree -= numMultiples; 90 | } 91 | 92 | // display result 93 | auto result = limit - notSquarefree; 94 | std::cout << result << std::endl; 95 | return 0; 96 | } 97 | -------------------------------------------------------------------------------- /euler-0197.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Investigating the behaviour of a recursively defined sequence 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=197 7 | // http://euler.stephan-brumme.com/197/ 8 | // 9 | // # Problem 10 | // Given is the function `f(x) = \lfloor 2^{30.403243784-x^2} \rfloor * 10^-9` ( `\lfloor \space \rfloor` is the floor-function), 11 | // the sequence `u_n` is defined by `u_0 = -1` and `u_{n+1} = f(u_n)`. 12 | // 13 | // Find `u_n + u_{n+1}` for `n = 10^12`. 14 | // Give your answer with 9 digits after the decimal point. 15 | // 16 | // # Solved by 17 | // Stephan Brumme 18 | // June 2017 19 | // 20 | // # Algorithm 21 | // The function ''f(x)'' is a straightforward implementation of the formula specified in the problem statement. 22 | // 23 | // I printed the first results "to get a feeling" for the value. It's obvious that they quickly converge to a bi-stabil state. 24 | // Assuming that this doesn't change, I computed `f(u_1000) + f(u_1001)` and hoped for the best ... and yes, got the correct answer. 25 | // 26 | // Actually you always get the correct answer after about 500 steps: `u_512 + u_513` are the smallest on my machine. 27 | // Depending on some rounding issues it's possible that you need more or less steps on your computer. 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | // compute next step 34 | double f(double x) 35 | { 36 | return floor(pow(2.0, 30.403243784 - x*x)) * pow(10, -9); 37 | } 38 | 39 | int main() 40 | { 41 | // initial value 42 | double u = -1; 43 | 44 | // compute next steps 45 | double next = f(u); 46 | for (unsigned int i = 1; i < 513; i++) 47 | { 48 | u = next; 49 | next = f(u); 50 | } 51 | 52 | // sum of two neighbors 53 | double result = u + next; 54 | 55 | std::cout << std::fixed << std::setprecision(9) << result << std::endl; 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /euler-0204.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Generalised Hamming Numbers 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=204 7 | // http://euler.stephan-brumme.com/204/ 8 | // 9 | // # Problem 10 | // A Hamming number is a positive number which has no prime factor larger than 5. 11 | // So the first few Hamming numbers are 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15. 12 | // There are 1105 Hamming numbers not exceeding `10^8`. 13 | // 14 | // We will call a positive number a generalised Hamming number of type `n`, if it has no prime factor larger than `n`. 15 | // Hence the Hamming numbers are the generalised Hamming numbers of type 5. 16 | // 17 | // How many generalised Hamming numbers of type 100 are there which don't exceed `10^9`? 18 | // 19 | // # Solved by 20 | // Stephan Brumme 21 | // May 2017 22 | // 23 | // # Algorithm 24 | // After all prime numbers between 2 and ''hamming'' are found, the function ''search'' builds all combinations of prime factors. 25 | 26 | #include 27 | #include 28 | 29 | // user-defined limits 30 | unsigned int limit = 1000000000; 31 | unsigned int hamming = 100; 32 | 33 | // short list of involved primes 34 | std::vector primes; 35 | 36 | // return number of hamming numbers where one prime factor is at least primes[indexMinPrime] 37 | // and which is a multiple of x 38 | unsigned int search(unsigned long long x = 1, unsigned int indexMinPrime = 0) 39 | { 40 | unsigned int result = 1; 41 | 42 | // multiply current number by all allowed primes 43 | for (auto i = indexMinPrime; i < primes.size(); i++) 44 | { 45 | auto product = primes[i] * x; 46 | 47 | // too large ? 48 | if (product > limit) 49 | break; 50 | 51 | // multiply by more primes 52 | result += search(product, i); 53 | } 54 | 55 | return result; 56 | } 57 | 58 | int main() 59 | { 60 | std::cin >> hamming >> limit; 61 | 62 | // the usual prime sieve 63 | for (unsigned int i = 2; i <= hamming; i++) 64 | { 65 | bool isPrime = true; 66 | for (auto p : primes) 67 | { 68 | if (p*p > i) 69 | break; 70 | if (i % p == 0) 71 | { 72 | isPrime = false; 73 | break; 74 | } 75 | } 76 | 77 | if (isPrime) 78 | primes.push_back(i); 79 | } 80 | 81 | // count hamming numbers 82 | std::cout << search() << std::endl; 83 | } 84 | -------------------------------------------------------------------------------- /euler-0205.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Dice Game 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=205 7 | // http://euler.stephan-brumme.com/205/ 8 | // 9 | // # Problem 10 | // Peter has nine four-sided (pyramidal) dice, each with faces numbered 1, 2, 3, 4. 11 | // Colin has six six-sided (cubic) dice, each with faces numbered 1, 2, 3, 4, 5, 6. 12 | // 13 | // Peter and Colin roll their dice and compare totals: the highest total wins. The result is a draw if the totals are equal. 14 | // 15 | // What is the probability that Pyramidal Pete beats Cubic Colin? Give your answer rounded to seven decimal places in the form ''0.abcdefg'' 16 | // 17 | // # Solved by 18 | // Stephan Brumme 19 | // May 2017 20 | // 21 | // # Algorithm 22 | // The function ''roll'' counts all possible outcomes when rolling a number of dices. 23 | // In ''main'' I iterate over all possible totals and count how often Peter wins against Colin: 24 | // 25 | // `beats_i = dfrac{ sum_{1..i-1}{six_i}}{ sum_{1..36}{six_i}}` 26 | // 27 | // `beats_i` has to be multiplied by the probability that Peter rolls `i`, which is: 28 | // 29 | // `roll_i = dfrac{four_i}{ sum_{1..36}{four_i}}` 30 | // 31 | // # Note 32 | // I wasn't sure how to submit my solution: whether I should type in the leading zero and the decimal dot - or not. 33 | // Turns out you should enter your result the way it is printed by the program, including both zero and dot. 34 | // 35 | // An interactive [live test](#live) is available for this problem. 36 | // 37 | // # Alternatives 38 | // My gut tells me there is a closed form to compute the result instantly. 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | // roll dices, store at count[x] how often the sum of all dices was exactly x 45 | void roll(unsigned int dices, unsigned int sides, std::vector& count, unsigned int sum = 0) 46 | { 47 | // rolled all dices, increment the sum's counter 48 | if (dices == 0) 49 | { 50 | count[sum]++; 51 | return; 52 | } 53 | 54 | // all combinations of a dice ... 55 | for (unsigned int i = 1; i <= sides; i++) 56 | roll(dices - 1, sides, count, sum + i); 57 | } 58 | 59 | int main() 60 | { 61 | unsigned int dicesPeter, sidesPeter; 62 | std::cin >> dicesPeter >> sidesPeter; // 6 6 63 | unsigned int dicesColin, sidesColin; 64 | std::cin >> dicesColin >> sidesColin; // 9 4 65 | 66 | // "high score", by default 9*4 = 6*6 = 36 67 | unsigned int maxTotal = std::max(dicesPeter * sidesPeter, dicesColin * sidesColin); 68 | 69 | // roll all 6x6 dices (Colin) 70 | std::vector colin(maxTotal + 1, 0); 71 | roll(dicesPeter, sidesPeter, colin); 72 | unsigned int sumColin = 0; // will be 46656 for 6,6 73 | for (auto x : colin) 74 | sumColin += x; 75 | 76 | // roll all 9x4 dices (Peter) 77 | std::vector peter(maxTotal + 1, 0); 78 | roll(dicesColin, sidesColin, peter); 79 | unsigned int sumPeter = 0; // will be 262144 for 9,4 80 | for (auto x : peter) 81 | sumPeter += x; 82 | 83 | // for each of Peter's potential dice sums, find how often it wins against Colin 84 | double winPeter = 0; 85 | for (unsigned int sum = 1; sum <= maxTotal; sum++) 86 | { 87 | // win if total is higher 88 | unsigned int numWins = 0; 89 | // => add all combinations of Colin that are smaller 90 | for (unsigned int j = 1; j < sum; j++) 91 | numWins += colin[j]; 92 | 93 | // compute percentage that current sum (Peter) wins against Colin 94 | double beats = numWins / double(sumColin); 95 | // add all of them ... 96 | winPeter += beats * peter[sum] / sumPeter; 97 | } 98 | 99 | // done ! 100 | std::cout << std::fixed << std::setprecision(7) << winPeter << std::endl; 101 | return 0; 102 | } 103 | -------------------------------------------------------------------------------- /euler-0206.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Concealed Square 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=206 7 | // http://euler.stephan-brumme.com/206/ 8 | // 9 | // # Problem 10 | // Find the unique positive integer whose square has the form 1_2_3_4_5_6_7_8_9_0, where each "_" is a single digit. 11 | // 12 | // # Solved by 13 | // Stephan Brumme 14 | // May 2017 15 | // 16 | // # Algorithm 17 | // The square must be between 1020304050607080900 (if all "_" are zeros) and 1929394959697989990 (if all "_" are nines). 18 | // That means I looking for a number `x` such that `sqrt{1020304050607080900} <= x <= sqrt{1929394959697989990}` which is 19 | // `1010101010 <= x <= 1389026623`. I named those constants ''MinNumber'' and ''MaxNumber''. 20 | // 21 | // The square's last digit is zero and that's only possible if the last digit of `x` is zero, too. 22 | // A simple loop iterates over all `x` in the aforementioned range which are multiples of 10 and calls ''match'' until it succeeds. 23 | // 24 | // ''match'' splits the ''square'' of ''x'' into single digits and compares them against a predefined array. 25 | // Since it's done from right-to-left, those digits are in reverse order. 26 | // 27 | // # Notes 28 | // My original code displayed the correct answer in about 250ms. 29 | // When I saw that it is very close to the upper limit of the for-loop I simply reversed it. 30 | // ==> now only 3ms ... and I feel like a cheater ! 31 | // 32 | // # Alternatives 33 | // You can probably solve this problem with pencil and paper: 34 | // - I already said that the last digit of ''x'' must be zero 35 | // - the next digit must be either 3 or 9 because only `3^2=9` or `7^2=49` end with a 9 36 | // - and so on ... 37 | 38 | #include 39 | 40 | // return true if root^2 matches 1_2_3_4_5_6_7_8_9_0 41 | bool match(unsigned long long x) 42 | { 43 | unsigned long long square = x * x; 44 | 45 | // required digits in reverse order 46 | const unsigned int Right2Left[] = { 0, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; 47 | unsigned int index = 0; 48 | 49 | // check all digits 50 | do 51 | { 52 | // right-most digits matches current element of Right2Left ? 53 | auto digit = square % 10; 54 | if (digit != Right2Left[index++]) 55 | return false; 56 | 57 | // remove the digit which passes the test and skip the next digit which is unknown, too 58 | square /= 100; 59 | } while (square > 0); 60 | 61 | // all tests passed ! 62 | return true; 63 | } 64 | 65 | int main() 66 | { 67 | // smallest possible number: gaps are zeros => sqrt(1020304050607080900) 68 | const unsigned int MinNumber = 1010101010; 69 | // largest possible number: gaps are nines => sqrt(1929394959697989990) 70 | const unsigned int MaxNumber = 1389026620; 71 | 72 | //for (unsigned int x = MinNumber; x <= MaxNumber; x += 10) 73 | for (unsigned int x = MaxNumber; x >= MinNumber; x -= 10) 74 | if (match(x)) 75 | { 76 | std::cout << x << std::endl; 77 | break; 78 | } 79 | 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /euler-0207.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Integer partition equations 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=207 7 | // http://euler.stephan-brumme.com/207/ 8 | // 9 | // # Problem 10 | // For some positive integers `k`, there exists an integer partition of the form `4^t = 2^t + k`, 11 | // where `4^t`, `2^t`, and `k` are all positive integers and `t` is a real number. 12 | // 13 | // The first two such partitions are `4^1 = 2^1 + 2` and `4^{1.5849625}... = 2^{1.5849625}... + 6`. 14 | // 15 | // Partitions where `t` is also an integer are called perfect. 16 | // For any `m >= 1` let `P(m)` be the proportion of such partitions that are perfect with `k <= m`. 17 | // Thus `P(6) = 1/2`. 18 | // 19 | // In the following table are listed some values of `P(m)` 20 | // 21 | // `P(5) = 1/1` 22 | // `P(10) = 1/2` 23 | // `P(15) = 2/3` 24 | // `P(20) = 1/2` 25 | // `P(25) = 1/2` 26 | // `P(30) = 2/5` 27 | // ... 28 | // `P(180) = 1/4` 29 | // `P(185) = 3/13` 30 | // 31 | // Find the smallest `m` for which `P(m) < 1/12345` 32 | // 33 | // # Solved by 34 | // Stephan Brumme 35 | // May 2017 36 | // 37 | // # Algorithm 38 | // The equation can be written as: 39 | // `4^t = 2^t + k` 40 | // `(2^t)^2 = 2^t + k` 41 | // 42 | // And if I replace `x = 2^t`: 43 | // `x^2 = x + k` 44 | // 45 | // My program iterates over all integer values of `x`. Then `x^2` must be an integer and `k` must be an integer, too. 46 | // 47 | // The problem statement already gave away that `x=2` is the smallest valid partition and is perfect, too (which means `t=1` because `2^1=2`). 48 | // My variables ''total'', ''perfect'' and ''x'' are initialized accordingly. 49 | // 50 | // `x = 2^t` is a __perfect__ partition if `t` is an integer. That means that only one bit of the binary representation of `x` is set 51 | // (left side is the power of two, right side how it is written in binary notation): 52 | // `2^1 = 10_2` 53 | // `2^2 = 100_2` 54 | // `2^3 = 1000_2` 55 | // `2^4 = 10000_2` 56 | // `2^5 = 100000_2` 57 | // `2^6 = 1000000_2` 58 | // `2^7 = 10000000_2` 59 | // ... 60 | // 61 | // My bit twiddling code from http://bits.stephan-brumme.com/isPowerOfTwo.html can figure out whether `x` is a power-of-two in just a few CPU cycles. 62 | // 63 | // As soon as the smallest `x` is known such that `dfrac{perfect}{total} < dfrac{1}{12345}`, the formula `x^2 = x + k` is translated to `k = x^2 - x` which produces the correct result. 64 | // 65 | // # Note 66 | // I added a small live test. You can the numerator and denominator for `P(m) = dfrac{numerator}{denominator}`, e.g. `dfrac{1}{1234}` ==> ''1 1234''. 67 | 68 | #include 69 | 70 | // return true, if x is a power of two 71 | bool isPowerOfTwo(unsigned int x) 72 | { 73 | // see http://bits.stephan-brumme.com/isPowerOfTwo.html 74 | return (x & (x - 1)) == 0; 75 | } 76 | 77 | int main() 78 | { 79 | // stop when proportion perfect/total is less than numerator/denominator 80 | unsigned int numerator = 1; 81 | unsigned int denominator = 12345; 82 | std::cin >> numerator >> denominator; 83 | 84 | if (numerator > denominator || numerator == 0) // check input: for live test only 85 | return 1; 86 | 87 | // count all valid partitions 88 | unsigned long long total = 1; 89 | // count perfect partitions 90 | unsigned long long perfect = 1; 91 | // x=2^t 92 | unsigned long long x = 3; 93 | // perfect/total > numerator/denominator is the same as 94 | // perfect*denominator > total*numerator 95 | while (perfect * denominator > total * numerator) 96 | { 97 | // found another perfect partition ? 98 | if (isPowerOfTwo(x)) 99 | perfect++; 100 | 101 | // keep going ... 102 | total++; 103 | x++; 104 | } 105 | 106 | // find k 107 | unsigned long long k = x * (x - 1); 108 | std::cout << k << std::endl; 109 | 110 | return 0; 111 | } 112 | -------------------------------------------------------------------------------- /euler-0211.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Divisor Square Sum 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=211 7 | // http://euler.stephan-brumme.com/211/ 8 | // 9 | // # Problem 10 | // For a positive integer `n`, let `\sigma(n)` be the sum of the squares of its divisors. For example, 11 | // `\sigma^2(10) = 1 + 4 + 25 + 100 = 130`. 12 | // 13 | // Find the sum of all `n`, `0 < n < 64,000,000` such that `\sigma^2(n)` is a perfect square. 14 | // 15 | // # Solved by 16 | // Stephan Brumme 17 | // May 2017 18 | // 19 | // # Algorithm 20 | // My approach works like a sieve: 21 | // - allocate enough memory for 64000000 numbers, each 64 bit (=> 512 MByte) 22 | // - fill it with zeros 23 | // - for each number 0 < i < 64000000: add i*i to each cell that is a multiple of i 24 | // - when done, check each cell whether it is a perfect square 25 | // 26 | // The initial solution was small and produced the correct result in about 10 seconds. 27 | // However, its memory consumption was much, much higher than any of my other solutions. 28 | // 29 | // Therefore I decided to move the algorithm to a new function ''processSlice'' which works a bit smarter: 30 | // instead of processing everything at once, it only looks at all numbers [''from, to'']. 31 | // Reducing ''to - from'' to about 4 million doesn't slow down the algorithm at all. 32 | // But I wanted to keep it below 20 MByte (for no good reason ...) and chose a ''sliceSize = 2000000'' which takes about 14 seconds (40% slower). 33 | // 34 | // # Alternative 35 | // You can play around with prime factorization. This should be a bit faster at the cost of probably doubling the code size. 36 | 37 | #include 38 | #include 39 | #include 40 | 41 | // determine the sum of all numbers between "from" and "to" (inclusive both) which match the problem statement 42 | unsigned long long processSlice(unsigned int from, unsigned int to) 43 | { 44 | std::vector sumSquares(to - from + 1, 0); 45 | // like a prime sieve: add square of all divisors 46 | for (unsigned long long i = 1; i <= to; i++) 47 | { 48 | // position of smallest multiple of i >= from 49 | auto pos = (from / i) * i; 50 | if (pos < from) 51 | pos += i; 52 | 53 | // add i^2 to all multiples of i 54 | for (; pos <= to; pos += i) 55 | sumSquares[pos - from] += i*i; 56 | } 57 | 58 | // find all sums that are perfect squares 59 | unsigned int sum = 0; 60 | for (size_t i = 0; i < sumSquares.size(); i++) 61 | { 62 | auto number = i + from; 63 | auto current = sumSquares[i]; 64 | 65 | // compute integer square root 66 | unsigned long long root = sqrt(current); 67 | // iff root^2 = current then it's a perfect square 68 | if (root * root == current) 69 | sum += number; 70 | } 71 | 72 | return sum; 73 | } 74 | 75 | int main() 76 | { 77 | unsigned int limit = 64000000; 78 | std::cin >> limit; 79 | 80 | // how many number should be analyzed at once (=> influences memory consumption) 81 | unsigned int sliceSize = 2000000; 82 | 83 | // total sum 84 | unsigned int sum = 0; 85 | // start of current slice 86 | unsigned int from = 1; 87 | while (from < limit) 88 | { 89 | // end of current slice 90 | auto to = from + sliceSize - 1; 91 | if (to >= limit) 92 | to = limit; 93 | 94 | // process current slice 95 | sum += processSlice(from, to); 96 | // next slice 97 | from = to + 1; 98 | } 99 | 100 | // print result 101 | std::cout << sum << std::endl; 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /euler-0235.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // An Arithmetic Geometric sequence 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=235 7 | // http://euler.stephan-brumme.com/235/ 8 | // 9 | // # Problem 10 | // Given is the arithmetic-geometric sequence `u(k) = (900-3k)r^{k-1}`. 11 | // Let `s(n) = sum_{k=1...n}u(k)`. 12 | // 13 | // Find the value of `r` for which `s(5000) = -600,000,000,000`. 14 | // 15 | // Give your answer rounded to 12 places behind the decimal point. 16 | // 17 | // # Solved by 18 | // Stephan Brumme 19 | // July 2017 20 | // 21 | // # Algorithm 22 | // The function `s_r(5000)` is monotonically decreasing: larger `r` reduce `s_r(5000)`. 23 | // 24 | // My program was inspired by the a classic bisection algorithm ( https://en.wikipedia.org/wiki/Bisection_method ): 25 | // 1. start with two reasonable upper and lower limits (I choose 0 and 2) 26 | // 2. find `mid = frac{upper+lower}{2}` and `s_{mid}(5000)` 27 | // 3. if the result is less than -600 billion then `mid` is too large and set `upper = mid` 28 | // 4. if the result is greater than -600 billion then `mid` is too small and set `lower = mid` 29 | // 5. if `upper - lower > 10^-12` then go to step 2. 30 | // 31 | // The ''pow'' function can be pretty slow. Incrementally computing `r^k` is about ten times faster (see ''#define SLOW''). 32 | // 33 | // # Note 34 | // I actually stop only after `upper - lower < 10^-13` because I was afraid of rounding issues. 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | //#define SLOW 41 | 42 | // compute s(r) according to problem statement 43 | double s(double r) 44 | { 45 | double result = 0; 46 | double x = 1; // r^0 is always 0 47 | for (int k = 1; k <= 5000; k++) 48 | { 49 | #ifdef SLOW 50 | result += (900 - 3 * k) * pow(r, k - 1); 51 | #else 52 | result += (900 - 3 * k) * x; 53 | x *= r; 54 | #endif 55 | } 56 | return result; 57 | } 58 | 59 | int main() 60 | { 61 | // initial lower and upper bounds 62 | double lower = 0; 63 | double upper = 2; 64 | 65 | // until the range is small enough 66 | while (upper - lower > 0.0000000000001) 67 | { 68 | double mid = (upper + lower) / 2; 69 | // find result at midpoint 70 | double current = s(mid); 71 | 72 | // adjust borders 73 | if (current < -600000000000.0) 74 | upper = mid; 75 | else 76 | lower = mid; 77 | } 78 | 79 | // print result (use midpoint but upper and/or lower should yield the same output) 80 | std::cout << std::fixed << std::setprecision(12) << (upper + lower) / 2 << std::endl; 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /euler-0265.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Binary Circles 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=265 7 | // http://euler.stephan-brumme.com/265/ 8 | // 9 | // # Problem 10 | // `2^N` binary digits can be placed in a circle so that all the `N`-digit clockwise subsequences are distinct. 11 | // 12 | // For `N=3`, two such circular arrangements are possible, ignoring rotations: 13 | // 14 | // ![binary circles](p265_BinaryCircles.gif) 15 | // 16 | // For the first arrangement, the 3-digit subsequences, in clockwise order, are: 17 | // 000, 001, 010, 101, 011, 111, 110 and 100. 18 | // 19 | // Each circular arrangement can be encoded as a number by concatenating the binary digits starting with the subsequence of all zeros 20 | // as the most significant bits and proceeding clockwise. The two arrangements for `N=3` are thus represented as 23 and 29: 21 | // `00010111_2 = 23` 22 | // `00011101_2 = 29` 23 | // 24 | // Calling `S(N)` the sum of the unique numeric representations, we can see that `S(3) = 23 + 29 = 52`. 25 | // 26 | // Find `S(5)`. 27 | // 28 | // # Solved by 29 | // Stephan Brumme 30 | // July 2017 31 | // 32 | // # Algorithm 33 | // I wrote a straightforward backtracking solution that start with `N` bits which are all zero and calls ''search'' recursively: 34 | // - try to append another zero, try to append another one 35 | // - if the most recent `N` bits occurred in the sequence before, then go back 36 | // - if the sequence has `2^N` bits, then another solution was found 37 | // 38 | // To simplify (read: to speed up) the search for "used" sub-sequences, a bitmask called ''history'' tracks all numbers. 39 | // If its k-th bit is used, then the number k is already part of the sequence. 40 | 41 | #include 42 | 43 | // N = number of bits 44 | unsigned int bits = 5; 45 | 46 | // find all valid results 47 | unsigned long long search(unsigned long long history, unsigned long long sequence) 48 | { 49 | // bitmask for all relevant bits 50 | const unsigned int Mask = (1 << bits) - 1; 51 | 52 | // seen all 2^bits bit combinations ? 53 | unsigned long long allBits = (1ULL << (1 << bits)) - 1; 54 | if (history == allBits) 55 | { 56 | // remove lowest bits (which are all zeros) 57 | sequence >>= bits - 1; 58 | return sequence; 59 | } 60 | 61 | // shift most recent bits one position to the left, remove highest bit 62 | unsigned int next = (sequence << 1) & Mask; 63 | 64 | // two options for the following value 65 | unsigned int zero = next; 66 | unsigned int one = next + 1; 67 | 68 | // sum of all found sequences 69 | unsigned long long result = 0; 70 | 71 | // check "zero" 72 | if ((history & (1ULL << zero)) == 0) 73 | result += search(history | (1ULL << zero), sequence << 1); 74 | 75 | // check "one" 76 | if ((history & (1ULL << one )) == 0) 77 | result += search(history | (1ULL << one ), (sequence << 1) | 1); 78 | 79 | return result; 80 | } 81 | 82 | int main() 83 | { 84 | std::cin >> bits; 85 | std::cout << search(1, 0) << std::endl; 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /euler-0279.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stbrumme/euler/b426763514558c3b39f2ec507f271d322088d28a/euler-0279.cpp -------------------------------------------------------------------------------- /euler-0301.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Nim 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=301 7 | // http://euler.stephan-brumme.com/301/ 8 | // 9 | // # Problem 10 | // Nim is a game played with heaps of stones, where two players take it in turn to remove any number of stones from any heap until no stones remain. 11 | // 12 | // We'll consider the three-heap normal-play version of Nim, which works as follows: 13 | // - At the start of the game there are three heaps of stones. 14 | // - On his turn the player removes any positive number of stones from any single heap. 15 | // - The first player unable to move (because no stones remain) loses. 16 | // 17 | // If (n1,n2,n3) indicates a Nim position consisting of heaps of size n1, n2 and n3 then there is a simple function X(n1,n2,n3) 18 | // that you may look up or attempt to deduce for yourself that returns: 19 | // 20 | // - zero if, with perfect strategy, the player about to move will eventually lose; or 21 | // - non-zero if, with perfect strategy, the player about to move will eventually win. 22 | // 23 | // For example X(1,2,3) = 0 because, no matter what the current player does, his opponent can respond with a move that leaves two heaps of equal size, at which point every move by the current player can be mirrored by his opponent until no stones remain; so the current player loses. To illustrate: 24 | // - current player moves to (1,2,1) 25 | // - opponent moves to (1,0,1) 26 | // - current player moves to (0,0,1) 27 | // - opponent moves to (0,0,0), and so wins. 28 | // 29 | // For how many positive integers `n <= 2^30` does X(n,2n,3n) = 0 ? 30 | // 31 | // # Solved by 32 | // Stephan Brumme 33 | // July 2017 34 | // 35 | // # Algorithm 36 | // This Wikipedia page told me that the "Nim Sum" is the XOR-result of all heaps: https://en.wikipedia.org/wiki/Nim 37 | // 38 | // # Note 39 | // I reversed the loop to iterate from `10^30` to `0` because then my compiler can produce code that is about 10% faster. 40 | // 41 | // # Alternative 42 | // Often I enter a few results into my search engine of choice - this time I was surprised to see that 43 | // the results for `2^1`, `2^2`, `2^3`, ... `2^n` are the (n+2)-th Fibonacci numbers. 44 | // Someone with more mathematical insight could probably seen that before writing the code - but I can't. 45 | // 46 | // It's possible to write a Dynamic Programming solution, too: 47 | // when n contains no two consecutive set bits then the game is lost. 48 | 49 | #include 50 | 51 | // see https://en.wikipedia.org/wiki/Nim 52 | unsigned int evaluate(unsigned int n1, unsigned int n2, unsigned int n3) 53 | { 54 | return n1 ^ n2 ^ n3; 55 | } 56 | 57 | int main() 58 | { 59 | // search up to n = 2^exponent 60 | unsigned int exponent = 30; 61 | std::cin >> exponent; 62 | 63 | unsigned int lost = 0; 64 | // 2^30 => about 1 billion values 65 | for (unsigned int n = 1U << exponent; n > 0; n--) 66 | { 67 | auto score = evaluate(n, 2*n, 3*n); 68 | if (score == 0) 69 | lost++; 70 | } 71 | 72 | std::cout << lost << std::endl; 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /euler-0346.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Strong Repunits 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=346 7 | // http://euler.stephan-brumme.com/346/ 8 | // 9 | // # Problem 10 | // The number 7 is special, because 7 is 111 written in base 2, and 11 written in base 6 11 | // (i.e. `7_10` = `11_6` = `111_2`). In other words, 7 is a repunit in at least two bases `b > 1`. 12 | // 13 | // We shall call a positive integer with this property a strong repunit. 14 | // It can be verified that there are 8 strong repunits below 50: {1,7,13,15,21,31,40,43}. 15 | // Furthermore, the sum of all strong repunits below 1000 equals 15864. 16 | // 17 | // Find the sum of all strong repunits below `10^12`. 18 | // 19 | // # Solved by 20 | // Stephan Brumme 21 | // July 2017 22 | // 23 | // # Algorithm 24 | // Each number `x` is a repunit in base `x-1`, more specific it's `11_{x-1} = (x-1)^1 + (x-1)^0 = x-1 + 1 = x`. 25 | // 26 | // A repunit in base 10 is `10^k + 10^{k-1} + 10^{k-2} + ... + 10^2 + 10^1 + 10^0`. 27 | // The same pattern surfaces for any base `b`: `b^k + b^{k-1} + b^{k-2} + ... + b^2 + b^1 + b^0` 28 | // 29 | // If I chase this sequence for each base `b` up to the limit `10^12` then I will find all strong repunits. 30 | // The only problem is that some numbers are strong repunits in more than two bases. 31 | // Those numbers are easily filtered by sorting and removing consecutive duplicates. 32 | 33 | #include 34 | #include 35 | #include 36 | 37 | int main() 38 | { 39 | // search limit 40 | auto limit = 1000000000000ULL; 41 | std::cin >> limit; 42 | 43 | // 1 is a strong unit in all bases 44 | std::vector found = { 1 }; 45 | 46 | // analyze other bases 47 | for (unsigned long long base = 2; base*base < limit; base++) 48 | { 49 | auto current = 1 + base + base * base; 50 | auto powers = base * base; 51 | while (current < limit) 52 | { 53 | found.push_back(current); 54 | powers *= base; 55 | current += powers; 56 | } 57 | } 58 | 59 | // remove duplicates 60 | std::sort(found.begin(), found.end()); 61 | auto last = std::unique(found.begin(), found.end()); 62 | found.erase(last, found.end()); 63 | 64 | // display sum of all elements 65 | unsigned long long sum = 0; 66 | for (auto x : found) 67 | sum += x; 68 | std::cout << sum << std::endl; 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /euler-0455.cpp: -------------------------------------------------------------------------------- 1 | // //////////////////////////////////////////////////////// 2 | // # Title 3 | // Powers With Trailing Digits 4 | // 5 | // # URL 6 | // https://projecteuler.net/problem=455 7 | // http://euler.stephan-brumme.com/455/ 8 | // 9 | // # Problem 10 | // Let `f(n)` be the largest positive integer `x` less than `10^9` such that the last 9 digits of `n^x` form the number `x` 11 | // (including leading zeros), or zero if no such integer exists. 12 | // 13 | // For example: 14 | // 15 | // `f(4) = 411728896` (`4^411728896 = ...411728896`) 16 | // `f(10) = 0` 17 | // `f(157) = 743757` (`157^743757 = ...000743757`) 18 | // `sum{f(n)}`, `2 <= n <= 10^3 = 442530011399` 19 | // 20 | // Find `sum{f(n)}`, `2 <= n <= 10^6`. 21 | // 22 | // # Solved by 23 | // Stephan Brumme 24 | // October 2017 25 | // 26 | // # Algorithm 27 | // The ''bruteForce()'' algorithm is super-slow and actually longer than my final solution. 28 | // And I found my final solution by chance: I used the last iteration's result as exponent instead of my loop variable. 29 | // `x_{i+1} = n^{x_i} mod 10^9` 30 | // 31 | // It turns out that there is "fix point" - if you repeat the procedure long enough then you will observe 32 | // `x_{j+1} = x_j` 33 | // 34 | // The only exception are powers of 10 where `x_j` will become zero. 35 | // 36 | // I was astonished to find that the initial value `x_0` doesn't really matter. 37 | // The number of iterations varies a little bit and seems to be quite low when `x_0 = n`. 38 | 39 | #include 40 | #include 41 | 42 | // ---------- 32 bit powmod from my toolbox ---------- 43 | 44 | // return (base^exponent) % modulo for 32-bit values, no need for mulmod 45 | unsigned int powmod(unsigned int base, unsigned int exponent, unsigned int modulo) 46 | { 47 | unsigned int result = 1; 48 | while (exponent > 0) 49 | { 50 | // fast exponentation: 51 | // odd exponent ? a^b = a*a^(b-1) 52 | if (exponent & 1) 53 | result = (result * (unsigned long long)base) % modulo; 54 | 55 | // even exponent ? a^b = (a*a)^(b/2) 56 | base = (base * (unsigned long long)base) % modulo; 57 | exponent >>= 1; 58 | } 59 | return result; 60 | } 61 | 62 | // ---------- problem specific code ---------- 63 | 64 | // try every possible exponent ... takes many minutes per number 65 | unsigned int bruteForce(unsigned int n, unsigned int modulo) 66 | { 67 | unsigned int result = modulo; 68 | while (result > 1) 69 | { 70 | result--; 71 | if (powmod(n, result, modulo) == result) 72 | break; 73 | if (result % 1000000 == 0) 74 | std::cout << n << " " << result << std::endl; 75 | } 76 | return result; 77 | } 78 | 79 | // find maximum exponent e such that n^e = e mod modulo 80 | unsigned int search(unsigned int n, unsigned int modulo) 81 | { 82 | unsigned int exponent = n; 83 | do 84 | { 85 | auto next = powmod(n, exponent, modulo); 86 | // stuck in a loop => we're finished 87 | if (next == 0 || next == exponent) 88 | return next; 89 | 90 | // keep going ... 91 | exponent = next; 92 | } while (true); 93 | } 94 | 95 | int main() 96 | { 97 | unsigned int limit = 1000000; 98 | std::cin >> limit; 99 | 100 | const unsigned int Modulo = 1000000000; 101 | 102 | //std::cout << bruteForce(4, Modulo) << std::endl; 103 | 104 | unsigned long long sum = 0; 105 | for (unsigned int i = 2; i <= limit; i++) 106 | sum += search(i, Modulo); 107 | 108 | std::cout << sum << std::endl; 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /p011_matrix.extra.txt: -------------------------------------------------------------------------------- 1 | 08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 2 | 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 3 | 81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 4 | 52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 5 | 22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 6 | 24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 7 | 32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70 8 | 67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21 9 | 24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72 10 | 21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95 11 | 78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 12 | 16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 13 | 86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 14 | 19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 15 | 04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 16 | 88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 17 | 04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 18 | 20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 19 | 20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 20 | 01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48 21 | -------------------------------------------------------------------------------- /p018_triangle.extra.txt: -------------------------------------------------------------------------------- 1 | 75 2 | 95 64 3 | 17 47 82 4 | 18 35 87 10 5 | 20 04 82 47 65 6 | 19 01 23 75 03 34 7 | 88 02 77 73 07 63 67 8 | 99 65 04 28 06 16 70 92 9 | 41 41 26 56 83 40 80 70 33 10 | 41 48 72 33 47 32 37 16 94 29 11 | 53 71 44 65 25 43 91 52 97 51 14 12 | 70 11 33 28 77 73 17 78 39 68 17 57 13 | 91 71 52 38 17 14 91 43 58 50 27 29 48 14 | 63 66 04 68 89 53 67 30 73 16 69 87 40 31 15 | 04 62 98 27 23 09 70 98 73 93 38 53 60 04 23 16 | -------------------------------------------------------------------------------- /p059_cipher.txt: -------------------------------------------------------------------------------- 1 | 79,59,12,2,79,35,8,28,20,2,3,68,8,9,68,45,0,12,9,67,68,4,7,5,23,27,1,21,79,85,78,79,85,71,38,10,71,27,12,2,79,6,2,8,13,9,1,13,9,8,68,19,7,1,71,56,11,21,11,68,6,3,22,2,14,0,30,79,1,31,6,23,19,10,0,73,79,44,2,79,19,6,28,68,16,6,16,15,79,35,8,11,72,71,14,10,3,79,12,2,79,19,6,28,68,32,0,0,73,79,86,71,39,1,71,24,5,20,79,13,9,79,16,15,10,68,5,10,3,14,1,10,14,1,3,71,24,13,19,7,68,32,0,0,73,79,87,71,39,1,71,12,22,2,14,16,2,11,68,2,25,1,21,22,16,15,6,10,0,79,16,15,10,22,2,79,13,20,65,68,41,0,16,15,6,10,0,79,1,31,6,23,19,28,68,19,7,5,19,79,12,2,79,0,14,11,10,64,27,68,10,14,15,2,65,68,83,79,40,14,9,1,71,6,16,20,10,8,1,79,19,6,28,68,14,1,68,15,6,9,75,79,5,9,11,68,19,7,13,20,79,8,14,9,1,71,8,13,17,10,23,71,3,13,0,7,16,71,27,11,71,10,18,2,29,29,8,1,1,73,79,81,71,59,12,2,79,8,14,8,12,19,79,23,15,6,10,2,28,68,19,7,22,8,26,3,15,79,16,15,10,68,3,14,22,12,1,1,20,28,72,71,14,10,3,79,16,15,10,68,3,14,22,12,1,1,20,28,68,4,14,10,71,1,1,17,10,22,71,10,28,19,6,10,0,26,13,20,7,68,14,27,74,71,89,68,32,0,0,71,28,1,9,27,68,45,0,12,9,79,16,15,10,68,37,14,20,19,6,23,19,79,83,71,27,11,71,27,1,11,3,68,2,25,1,21,22,11,9,10,68,6,13,11,18,27,68,19,7,1,71,3,13,0,7,16,71,28,11,71,27,12,6,27,68,2,25,1,21,22,11,9,10,68,10,6,3,15,27,68,5,10,8,14,10,18,2,79,6,2,12,5,18,28,1,71,0,2,71,7,13,20,79,16,2,28,16,14,2,11,9,22,74,71,87,68,45,0,12,9,79,12,14,2,23,2,3,2,71,24,5,20,79,10,8,27,68,19,7,1,71,3,13,0,7,16,92,79,12,2,79,19,6,28,68,8,1,8,30,79,5,71,24,13,19,1,1,20,28,68,19,0,68,19,7,1,71,3,13,0,7,16,73,79,93,71,59,12,2,79,11,9,10,68,16,7,11,71,6,23,71,27,12,2,79,16,21,26,1,71,3,13,0,7,16,75,79,19,15,0,68,0,6,18,2,28,68,11,6,3,15,27,68,19,0,68,2,25,1,21,22,11,9,10,72,71,24,5,20,79,3,8,6,10,0,79,16,8,79,7,8,2,1,71,6,10,19,0,68,19,7,1,71,24,11,21,3,0,73,79,85,87,79,38,18,27,68,6,3,16,15,0,17,0,7,68,19,7,1,71,24,11,21,3,0,71,24,5,20,79,9,6,11,1,71,27,12,21,0,17,0,7,68,15,6,9,75,79,16,15,10,68,16,0,22,11,11,68,3,6,0,9,72,16,71,29,1,4,0,3,9,6,30,2,79,12,14,2,68,16,7,1,9,79,12,2,79,7,6,2,1,73,79,85,86,79,33,17,10,10,71,6,10,71,7,13,20,79,11,16,1,68,11,14,10,3,79,5,9,11,68,6,2,11,9,8,68,15,6,23,71,0,19,9,79,20,2,0,20,11,10,72,71,7,1,71,24,5,20,79,10,8,27,68,6,12,7,2,31,16,2,11,74,71,94,86,71,45,17,19,79,16,8,79,5,11,3,68,16,7,11,71,13,1,11,6,1,17,10,0,71,7,13,10,79,5,9,11,68,6,12,7,2,31,16,2,11,68,15,6,9,75,79,12,2,79,3,6,25,1,71,27,12,2,79,22,14,8,12,19,79,16,8,79,6,2,12,11,10,10,68,4,7,13,11,11,22,2,1,68,8,9,68,32,0,0,73,79,85,84,79,48,15,10,29,71,14,22,2,79,22,2,13,11,21,1,69,71,59,12,14,28,68,14,28,68,9,0,16,71,14,68,23,7,29,20,6,7,6,3,68,5,6,22,19,7,68,21,10,23,18,3,16,14,1,3,71,9,22,8,2,68,15,26,9,6,1,68,23,14,23,20,6,11,9,79,11,21,79,20,11,14,10,75,79,16,15,6,23,71,29,1,5,6,22,19,7,68,4,0,9,2,28,68,1,29,11,10,79,35,8,11,74,86,91,68,52,0,68,19,7,1,71,56,11,21,11,68,5,10,7,6,2,1,71,7,17,10,14,10,71,14,10,3,79,8,14,25,1,3,79,12,2,29,1,71,0,10,71,10,5,21,27,12,71,14,9,8,1,3,71,26,23,73,79,44,2,79,19,6,28,68,1,26,8,11,79,11,1,79,17,9,9,5,14,3,13,9,8,68,11,0,18,2,79,5,9,11,68,1,14,13,19,7,2,18,3,10,2,28,23,73,79,37,9,11,68,16,10,68,15,14,18,2,79,23,2,10,10,71,7,13,20,79,3,11,0,22,30,67,68,19,7,1,71,8,8,8,29,29,71,0,2,71,27,12,2,79,11,9,3,29,71,60,11,9,79,11,1,79,16,15,10,68,33,14,16,15,10,22,73 2 | -------------------------------------------------------------------------------- /p079_keylog.txt: -------------------------------------------------------------------------------- 1 | 319 2 | 680 3 | 180 4 | 690 5 | 129 6 | 620 7 | 762 8 | 689 9 | 762 10 | 318 11 | 368 12 | 710 13 | 720 14 | 710 15 | 629 16 | 168 17 | 160 18 | 689 19 | 716 20 | 731 21 | 736 22 | 729 23 | 316 24 | 729 25 | 729 26 | 710 27 | 769 28 | 290 29 | 719 30 | 680 31 | 318 32 | 389 33 | 162 34 | 289 35 | 162 36 | 718 37 | 729 38 | 319 39 | 790 40 | 680 41 | 890 42 | 362 43 | 319 44 | 760 45 | 316 46 | 729 47 | 380 48 | 319 49 | 728 50 | 716 51 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | _This is a mirror of my C++ solutions for about half of the_ [Project Euler](https://projecteuler.net) _problems_ 2 | 3 | You can find the code along with in-depth explanations and live demos at https://euler.stephan-brumme.com 4 | 5 | Below is an excerpt from https://euler.stephan-brumme.com/why/ : 6 | 7 | 8 | # Why do I publish my solutions ? 9 | 10 | Almost always the solutions for problems at Project Euler consist of two parts: 11 | 1. finding a mathematical way to break down the problem's structure into its elements 12 | 2. writing an efficient program for step 1 13 | 14 | I strive to: 15 | * explain my choice of algorithms and data structures 16 | * write fully commented C++ source code that compiles without warnings and _without any external libraries_ 17 | * interactive tests for most problems 18 | * link to relevant [Wikipedia](https://en.wikipedia.org) / [MathWorld](http://mathworld.wolfram.com) / [OEIS](https://oeis.org) pages 19 | * link to other solutions, especially those that are written in other programming languages 20 | 21 | Let's not forget that it helps me, too: only if I can explain a solution to someone else then I can be sure _that I truly understood it in the first place_. 22 | And practicing some of the lesser used features of C++ (such as algorithms hidden inside STL, like **std::next_permutation**) improves my overall coding skills as well. 23 | 24 | Sounds like a win-win situation ... 25 | 26 | 27 | # "But You Shouldn't Publish Your Solutions !" 28 | 29 | Project Euler encourages you **NOT** to publish solutions. 30 | 31 | I have a different point of view: 32 | * 99% of my knowledge is based on things I was taught, I saw somewhere or I stumbled across 33 | * and maybe 1% is "original" 34 | * I'm pretty sure it's not just me - it's the way how all of us gain knowledge 35 | 36 | So it boils down to: 37 | * having a good teacher 38 | * access to well-equipped library 39 | * and probably most important today: your skills in working with a search engine 40 | 41 | If someone visits my website/repository then he/she already realized that he/she can't solve that problem and is doing the right thing: ask someone. 42 | That's the only way how knowledge can be spread - all famous scientists wrote books. 43 | [Leonhard Euler](https://en.wikipedia.org/wiki/Leonhard_Euler) was one of the most productive mathematicians and he published 866 papers/books/etc. He shared his knowledge. 44 | And a substantial number of my solutions is based on some of his formulas, I only solved them because I could look up his works. 45 | 46 | Admittedly, there is no use in publishing lists of the results to Project Euler problems. In my opinion, these numbers don't matter at all: 47 | noone really cares whether the result of [problem 1](https://euler.stephan-brumme.com/1/) is 233167, 233168 or 233169. 48 | That's why you find algorithms, explanations, links, code, ..., basically everything on my website - but not the results. 49 | Because these numbers don't teach you anything. 50 | --------------------------------------------------------------------------------