#include <iostream> #include <bitset> #include <vector> #include <set> #include <math.h> using namespace std; /* 0 < a < b < c a + b + c = n 1 <= n <= 10^9 b = x * a c = y * b = x * y * a a < b => x > 1 b < c => y > 1 a + b + c = n a + xa + xya = n a * (1 + x * (1 + y)) = n max_n = 10^9 min_x = 2 min_y = 2 max_a * (1 + min_x * (1 + min_y)) = max_n max_a * (1 + 2 * (1 + 2)) = max_n max_a * 7 = max_n max_a = max_n / 7 for a == 1: 1 + max_x * (1 + min_y) = max_n max_x * (1 + 2) = max_n - 1 max_x ~= max_n / 3 max_prime = sqrt(max_n) m = n / a - 1 x * (1 + y) = m max_x * (1 + min_y) = max_m max_x * (1 + 2) = max_m max_x * 3 = max_m max_x = max_m / 3 */ const unsigned long MAX_N = 1000000000; const unsigned long MAX_PRIME = (unsigned long) sqrt(MAX_N); bitset<MAX_PRIME> reverseOddPrimes; // false == prime bool isPrime(unsigned long number) { if (number < 2) return false; if (number == 2) return true; if (number % 2 == 0) return false; return !reverseOddPrimes.test((number - 1) / 2); } void calculatePrimes(unsigned long maxPrime) { unsigned long oddPrimesLimit = maxPrime / 2 + 1; for (unsigned long x = 1; x <= oddPrimesLimit; ++x) { if (!reverseOddPrimes.test(x)) { unsigned long jump = x * 2 + 1; for (unsigned long y = x + jump; y <= oddPrimesLimit; y = y + jump) { reverseOddPrimes.set(y); } } } } vector<unsigned long> getPrimes(unsigned long maxPrime) { unsigned long oddPrimesLimit = maxPrime / 2 + 1; vector<unsigned long> primes; primes.push_back(2); for (unsigned long x = 1; x <= oddPrimesLimit; ++x) { if (!reverseOddPrimes.test(x)) primes.push_back(x * 2 + 1); } return primes; } vector<unsigned long> getPrimeFactors(unsigned long number) { unsigned long limit = (unsigned long) sqrt(number) + 1; vector<unsigned long> factors; vector<unsigned long> primes = getPrimes(limit); vector<unsigned long>::iterator primeIt = primes.begin(); unsigned long x = number; while ((x != 1) && (primeIt != primes.end())) { if (x % *primeIt == 0) { factors.push_back(*primeIt); x = x / *primeIt; } else { ++primeIt; } } if (x != 1) { factors.push_back(x); } return factors; } set<unsigned long> getProperDivisors(unsigned long number, unsigned long maximum) { set<unsigned long> divisors; divisors.insert(1); if (number == 1) return divisors; vector<unsigned long> factors = getPrimeFactors(number); for (vector<unsigned long>::iterator factorsIt = factors.begin(); factorsIt != factors.end(); ++factorsIt) { set<unsigned long> newDivisors; for (set<unsigned long>::iterator divisorsIt = divisors.begin(); divisorsIt != divisors.end(); ++divisorsIt) { unsigned long product = *divisorsIt * *factorsIt; if ((product <= maximum) && (product < number)) { newDivisors.insert(product); } } divisors.insert(newDivisors.begin(), newDivisors.end()); } return divisors; } int main() { unsigned long resultCounter = 0; unsigned long n; cin >> n; calculatePrimes((unsigned long) sqrt(n) + 1); set<unsigned long> nDivisors = getProperDivisors(n, n / 7); for (set<unsigned long>::iterator aIt = nDivisors.begin(); aIt != nDivisors.end(); ++aIt) { // cout << " a=" << *aIt << endl; unsigned long m = n / *aIt - 1; set<unsigned long> mDivisors = getProperDivisors(m, m / 3); for (set<unsigned long>::iterator xIt = mDivisors.begin(); xIt != mDivisors.end(); ++xIt) { // cout << " x=" << *xIt << endl; if (*xIt < 2) continue; unsigned long y = m / *xIt - 1; if (y < 2) continue; if (*aIt * (1 + *xIt * (1 + y)) == n) { ++resultCounter; // cout << resultCounter << ": " << *aIt << " " << *aIt * *xIt << " " << *aIt * *xIt * y << endl; } } } cout << resultCounter; return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | #include <iostream> #include <bitset> #include <vector> #include <set> #include <math.h> using namespace std; /* 0 < a < b < c a + b + c = n 1 <= n <= 10^9 b = x * a c = y * b = x * y * a a < b => x > 1 b < c => y > 1 a + b + c = n a + xa + xya = n a * (1 + x * (1 + y)) = n max_n = 10^9 min_x = 2 min_y = 2 max_a * (1 + min_x * (1 + min_y)) = max_n max_a * (1 + 2 * (1 + 2)) = max_n max_a * 7 = max_n max_a = max_n / 7 for a == 1: 1 + max_x * (1 + min_y) = max_n max_x * (1 + 2) = max_n - 1 max_x ~= max_n / 3 max_prime = sqrt(max_n) m = n / a - 1 x * (1 + y) = m max_x * (1 + min_y) = max_m max_x * (1 + 2) = max_m max_x * 3 = max_m max_x = max_m / 3 */ const unsigned long MAX_N = 1000000000; const unsigned long MAX_PRIME = (unsigned long) sqrt(MAX_N); bitset<MAX_PRIME> reverseOddPrimes; // false == prime bool isPrime(unsigned long number) { if (number < 2) return false; if (number == 2) return true; if (number % 2 == 0) return false; return !reverseOddPrimes.test((number - 1) / 2); } void calculatePrimes(unsigned long maxPrime) { unsigned long oddPrimesLimit = maxPrime / 2 + 1; for (unsigned long x = 1; x <= oddPrimesLimit; ++x) { if (!reverseOddPrimes.test(x)) { unsigned long jump = x * 2 + 1; for (unsigned long y = x + jump; y <= oddPrimesLimit; y = y + jump) { reverseOddPrimes.set(y); } } } } vector<unsigned long> getPrimes(unsigned long maxPrime) { unsigned long oddPrimesLimit = maxPrime / 2 + 1; vector<unsigned long> primes; primes.push_back(2); for (unsigned long x = 1; x <= oddPrimesLimit; ++x) { if (!reverseOddPrimes.test(x)) primes.push_back(x * 2 + 1); } return primes; } vector<unsigned long> getPrimeFactors(unsigned long number) { unsigned long limit = (unsigned long) sqrt(number) + 1; vector<unsigned long> factors; vector<unsigned long> primes = getPrimes(limit); vector<unsigned long>::iterator primeIt = primes.begin(); unsigned long x = number; while ((x != 1) && (primeIt != primes.end())) { if (x % *primeIt == 0) { factors.push_back(*primeIt); x = x / *primeIt; } else { ++primeIt; } } if (x != 1) { factors.push_back(x); } return factors; } set<unsigned long> getProperDivisors(unsigned long number, unsigned long maximum) { set<unsigned long> divisors; divisors.insert(1); if (number == 1) return divisors; vector<unsigned long> factors = getPrimeFactors(number); for (vector<unsigned long>::iterator factorsIt = factors.begin(); factorsIt != factors.end(); ++factorsIt) { set<unsigned long> newDivisors; for (set<unsigned long>::iterator divisorsIt = divisors.begin(); divisorsIt != divisors.end(); ++divisorsIt) { unsigned long product = *divisorsIt * *factorsIt; if ((product <= maximum) && (product < number)) { newDivisors.insert(product); } } divisors.insert(newDivisors.begin(), newDivisors.end()); } return divisors; } int main() { unsigned long resultCounter = 0; unsigned long n; cin >> n; calculatePrimes((unsigned long) sqrt(n) + 1); set<unsigned long> nDivisors = getProperDivisors(n, n / 7); for (set<unsigned long>::iterator aIt = nDivisors.begin(); aIt != nDivisors.end(); ++aIt) { // cout << " a=" << *aIt << endl; unsigned long m = n / *aIt - 1; set<unsigned long> mDivisors = getProperDivisors(m, m / 3); for (set<unsigned long>::iterator xIt = mDivisors.begin(); xIt != mDivisors.end(); ++xIt) { // cout << " x=" << *xIt << endl; if (*xIt < 2) continue; unsigned long y = m / *xIt - 1; if (y < 2) continue; if (*aIt * (1 + *xIt * (1 + y)) == n) { ++resultCounter; // cout << resultCounter << ": " << *aIt << " " << *aIt * *xIt << " " << *aIt * *xIt * y << endl; } } } cout << resultCounter; return 0; } |