- 论坛徽章:
- 1
|
又用C++实现了一下这个算法,结果大大地出乎我的意料{:3_189:}
witch:~/Documents/workspace/Flower$ time ./a.out 21
449177399146038697307
128468643043731391252
real 0m9.627s
user 0m9.582s
sys 0m0.008s
witch:~/Documents/workspace/Flower$ time ./a.out 24
174088005938065293023722
188451485447897896036875
239313664430041569350093
real 0m22.139s
user 0m22.119s
sys 0m0.006s
- #include <cstdio>
- #include <cstring>
- #include <cstdlib>
- template<int LENGTH>
- class Integer {
- typedef unsigned int U32;
- typedef unsigned long long U64;
- public:
- Integer() {
- for (int i = 0; i < LENGTH; ++i) {
- data[i] = 0;
- }
- }
- Integer(U32 that) {
- copy(that);
- }
- const Integer& operator = (U32 that) {
- copy(that);
- return *this;
- }
- const Integer& operator += (const Integer& that) {
- int carry = 0;
- for (int i = 0; i < LENGTH; ++i) {
- data[i] += that.data[i] + carry;
- if (data[i] > BASE) {
- carry = data[i] / BASE;
- data[i] = data[i] % BASE;
- } else {
- carry = 0;
- }
- }
- return *this;
- }
- const Integer& operator *= (U32 that) {
- U64 carry = 0;
- for (int i = 0; i < LENGTH; ++i) {
- U64 tmp = (U64)data[i] * (U64)that + carry;
- if (tmp > BASE) {
- carry = tmp / BASE;
- data[i] = tmp % BASE;
- } else {
- carry = 0;
- data[i] = tmp;
- }
- }
- return *this;
- }
- Integer operator + (const Integer& that) const {
- Integer tmp = *this;
- return tmp += that;
- }
- Integer operator * (U32 that) const {
- Integer tmp = *this;
- return tmp *= that;
- }
- bool operator < (const Integer& that) const {
- for (int i = LENGTH - 1; i >= 0; --i) {
- if (data[i] < that.data[i]) {
- return true;
- } else if (data[i] > that.data[i]) {
- return false;
- }
- }
- return false;
- }
- bool operator > (const Integer& that) const {
- return std::memcmp(data, that.data, sizeof(data)) != 0
- && !(*this < that);
- }
- void validate(char digit[9]) const {
- char decimal[LENGTH * WIDTH + 1];
- toString(decimal);
- char actual[10] = {0};
- for (int i = 0; i < WIDTH * LENGTH; ++i) {
- ++actual[decimal[i] - '0'];
- }
- if (std::memcmp(actual + 1, digit, 9) == 0) {
- output(decimal);
- }
- }
- void toString(char* decimal) const {
- for (int i = LENGTH - 1; i >= 0; --i) {
- std::sprintf(decimal + WIDTH * (LENGTH - 1 - i), "%09d", data[i]);
- }
- decimal[LENGTH * WIDTH] = 0;
- }
- void show() const {
- char decimal[LENGTH * WIDTH + 1];
- toString(decimal);
- printf("%s\n", decimal);
- }
- private:
- enum {
- BASE = 1000000000, /* This is 10^9 */
- WIDTH = 9
- };
- U32 data[LENGTH];
- void copy(U32 that) {
- data[0] = that % BASE;
- data[1] = that / BASE;
- for (int i = 2; i < LENGTH; ++i) {
- data[i] = 0;
- }
- }
- static void output(const char* decimal) {
- int i = 0;
- while (decimal[i] == '0') {
- ++i;
- }
- printf("%s\n", decimal + i);
- }
- };
- typedef Integer<3> Bigint;
- Bigint MIN;
- Bigint MAX;
- Bigint** TABLE;
- void createSumTable(int length) {
- TABLE = new Bigint*[9];
- for (int i = 0; i < 9; ++i) {
- TABLE[i] = new Bigint[length];
- TABLE[i][0] = i + 1;
- for (int j = 1; j < length; ++j) {
- TABLE[i][0] *= (i + 1);
- }
- for (int j = 1; j < length; ++j) {
- TABLE[i][j] = TABLE[i][0] * (j + 1);
- }
- }
- }
- void initialize(int length) {
- MIN = 10;
- for (int i = 0; i < length - 2; ++i) {
- MIN *= 10;
- }
- MAX = MIN * 10;
- createSumTable(length);
- }
- void search(int left, int index, Bigint partialSum, char* digit) {
- if (index < 8 && left > 0) {
- search(left, index + 1, partialSum, digit);
- }
- for (int count = 1; count < left + 1; ++count) {
- digit[index] = count;
- Bigint sum = partialSum + TABLE[index][count - 1];
- if (sum > MAX) {
- break;
- }
- if (sum > MIN) {
- sum.validate(digit);
- }
- if (index < 8 && left > count) {
- search(left - count, index + 1, sum, digit);
- }
- }
- digit[index] = 0;
- }
- int main(int argc, char** argv) {
- int length = 0;
- if (argc != 2 || sscanf(argv[1], "%d", &length) != 1 || length <= 0) {
- std::fprintf(stderr, "Usage: %s <length>\n", argv[0]);
- }
- initialize(length);
- char* digit = (char*)std::calloc(length, 1);
- search(length, 0, Bigint(0), digit);
- return 0;
- }
复制代码 |
|