From db62517be1e5d1609d5121a17a4c5833ef989caf Mon Sep 17 00:00:00 2001 From: zhangbo Date: Fri, 23 Feb 2024 00:17:21 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E4=B8=80=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 ++++ ReciprocalSearch.cpp | 122 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 ReciprocalSearch.cpp diff --git a/README.md b/README.md index 1d26125..9b1c34b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,11 @@ # ReciprocalSearch 在1到100中找10个不同的数,使其倒数和为1。从小到大排列这10个数,有一个不同就视为不同的解。求所有的解。 + +程序的原始版本不是我写的。 + +基本思路是用抽屉原则,确定每重循环/递归的搜索上限,进行剪枝。 +比如:最开始的和是1,这个和需要分给10个数,那么至少有一个数分到的值是不小于1/10的,那么第一重循环的上限不大于10。 + +计算出来后,用大数运算库GMP校验一下,有71312个是对的(未去重)。校验的时候,第10个整数分别用(int)i10、(int)i10 + 1、(int)i10 - 1去尝试。 + +整个代码也可以不用double来运算,而是用GMP的自然数库来运算。 diff --git a/ReciprocalSearch.cpp b/ReciprocalSearch.cpp new file mode 100644 index 0000000..a563243 --- /dev/null +++ b/ReciprocalSearch.cpp @@ -0,0 +1,122 @@ +#include +#include + +#pragma warning(disable:4146) +#include + +#define min(a,b) (((a)<(b))?(a):(b)) + +bool check(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10) { + int a[10]; + + a[0] = i1; + a[1] = i2; + a[2] = i3; + a[3] = i4; + a[4] = i5; + a[5] = i6; + a[6] = i7; + a[7] = i8; + a[8] = i9; + a[9] = i10; + + mpz_t t; + mpz_init(t); + mpz_set_ui(t, 1); + for (int k = 0; k < 10; ++k) { + mpz_mul_ui(t, t, a[k]); + } + + mpz_t s; + mpz_init(s); + mpz_set_ui(s, 0); + + mpz_t t1; + mpz_init(t1); + for (int k = 0; k < 10; ++k) { + mpz_div_ui(t1, t, a[k]); + mpz_add(s, s, t1); + } + + bool valid = (mpz_cmp(s, t) == 0); + + mpz_clear(t); + mpz_clear(s); + mpz_clear(t1); + + return valid; +} + +int main() { + int total = 0; + int valid = 0; + + double ii[101]; + + for (int i = 1; i <= 100; i++) { ii[i] = 1.0 / i; } + + for (int i1 = 2; i1 <= 10; i1++) { + double m1 = 1 - ii[i1]; + + for (int i2 = i1 + 1; i2 < min(92, (int)(9.0 / m1) + 1); i2++) { + double m2 = m1 - ii[i2]; + + for (int i3 = i2 + 1; i3 < min(93, (int)(8.0 / m2) + 1); i3++) { + double m3 = m2 - ii[i3]; + if (m3 <= 0) { continue; } + + for (int i4 = i3 + 1; i4 < min(94, (int)(7.0 / m3) + 1); i4++) { + double m4 = m3 - ii[i4]; + if (m4 <= 0) { continue; } + + for (int i5 = i4 + 1; i5 < min(95, (int)(6.0 / m4) + 1); i5++) { + double m5 = m4 - ii[i5]; + if (m5 <= 0) { continue; } + + for (int i6 = i5 + 1; i6 < min(96, (int)(5.0 / m5) + 1); i6++) { + double m6 = m5 - ii[i6]; + if (m6 <= 0) { continue; } + + for (int i7 = i6 + 1; i7 < min(97, (int)(4.0 / m6) + 1); i7++) { + double m7 = m6 - ii[i7]; + if (m7 <= 0) { continue; } + + for (int i8 = i7 + 1; i8 < min(98, (int)(3.0 / m7) + 1); i8++) { + double m8 = m7 - ii[i8]; + if (m8 <= 0) { continue; } + + for (int i9 = i8 + 1; i9 < min(99, (int)(2.0 / m8) + 1); i9++) { + double m9 = m8 - ii[i9]; + + if (m9 <= 0.01) { continue; } + double i10 = 1.0 / m9; + + if (fabs(i10 - round(i10)) < 0.000001) { + ++total; + + if (check(i1, i2, i3, i4, i5, i6, i7, i8, i9, (int)i10)) { + ++valid; + printf("%d %d %d %d %d %d %d %d %d %.4f(%d)\n", i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, (int)i10); + } else if (check(i1, i2, i3, i4, i5, i6, i7, i8, i9, (int)i10 + 1)) { + ++valid; + printf("%d %d %d %d %d %d %d %d %d %.4f(%d)\n", i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, (int)i10 + 1); + } else if (check(i1, i2, i3, i4, i5, i6, i7, i8, i9, (int)i10 - 1)) { + ++valid; + printf("%d %d %d %d %d %d %d %d %d %.4f(%d)\n", i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, (int)i10 - 1); + } + else { + printf("%d %d %d %d %d %d %d %d %d %.4f INVALID\n", i1, i2, i3, i4, i5, i6, i7, i8, i9, i10); + } + } + } + } + } + } + } + } + } + } + } + + printf("total %d, valid = %d\n", total, valid); +} \ No newline at end of file