C ++ 11
Подальше невелике оновлення: зробіть набагато менше додавання та спробуйте всі цифри форми A * B + C. Я вважаю , що в протягом терміну, це досить близько до оптимального, якщо ви використовуєте тільки +
, *
і !
. Я залишаю інших операторів людям, які мають більше часу, ніж я!
Невелике оновлення: Намагайтеся сильніше використовувати фактичні факти та номери, наприклад 11 .... 111. Також виправлена помилка, яку я не рахував !
у своїй вартості
Новий результат:
Первинний показник = 3 810 660
Середня оцінка = 12.09.2016 20:00
2532 1
с, 1505 операторів.
Різні трюки складаються разом. Моя програма починається з встановлення найкоротшої програми для всіх фабрик і номерів форми 111..111 (я не думаю, що це не відповідає принципу жорсткої проводки, оскільки це найкоротші способи зробити ці числа. Я міг би переставити мій код, тому я перевіряю ці зразки в своєму динамічному програмуванні, якщо ви хочете). Потім виконайте частковий динамічний підхід до програмування, приміряючи різні форми:
- A + B
- A * B + C
- A! + В
- 11 .... 11 + В
На жаль, я не можу спробувати всі способи декомпозиції числа, тому я вибираю для факториалів і 11 ... 11 лише спробувати найближче число, для A + B спробувати речі поблизу A / 2, а для A * B + C спробувати лише зовсім маленький As.
Було б легко розширити це, щоб спробувати деякі '', намагаючись іноді трохи перевертати (особливо в A * B - C), але мені дуже подобається лише намагатися рости.
Крім того, дуже важко оптимізувати умову оптимізації (мені це не подобається!), Оскільки в принципі ви не можете підібрати «найкраще» значення для кожного номера ізольовано, ви повинні розглянути свій набір відповідей у всьому світі. (чого я не збираюся робити).
Попередження: цій програмі потрібен 64-розрядний апарат і близько 10 ГБ пам'яті (оскільки я неефективно створюю гігантський масив для всіх частково обчислених результатів).
Програма:
#include <algorithm>
#include <vector>
#include <string>
#include <assert.h>
#include <iostream>
#include <cmath>
std::vector<int> numints;
std::vector<int> numops;
std::vector<std::string> strings;
void fill_all_ones(long maxval)
{
int val = 1;
int len = 1;
std::string name = "1";
while(val < maxval) {
val = val * 10 + 1;
len++;
name = name + "1";
numints[val] = len;
strings[val] = name;
}
}
void get_best_for_next_full(long i);
// let's just assume this is the best way to make factorials
void fill_all_factorials(long maxval)
{
// skip 1 and 2
long result = 6;
long val = 3;
while(result < maxval) {
get_best_for_next_full(val);
strings[result] = "(" + strings[val] + ")!";
numints[result] = numints[val];
numops[result] = numops[val] + 1;
val++;
result = result * val;
}
}
long get_nearest_all_ones(long i)
{
int val = 11;
int prevval = 1;
while(val < i) {
prevval = val;
val = val * 10 + 1;
}
return prevval;
}
long get_nearest_factorial(long i)
{
int val = 6;
int prevval = 2;
int step = 3;
while(val < i) {
prevval = val;
step++;
val = val * step;
}
return prevval;
}
int getlen(long i);
void get_best_for_next_full(long i)
{
if(numints[i] > 0)
return;
int best = INT_MAX; // we'll do better than this
std::string beststring = "invalid2";
int ones = -1;
int ops = -1;
for(long loop = 1; loop <= i/2; loop++)
{
int new_val = getlen(loop) + getlen(i - loop);
if(new_val < best) {
best = new_val;
ones = numints[loop] + numints[i - loop];
beststring = "(" + strings[loop] + "+" + strings[i - loop] + ")";
ops = numops[loop] + numops[i - loop] + 1;
}
}
for(long loop = 2; loop * loop <= i; loop++)
{
long divisor = i / loop;
long rem = i - loop*divisor;
assert(rem >= 0);
int new_val;
if(rem == 0)
{
new_val = getlen(divisor) + getlen(loop);
}
else
{
new_val = getlen(divisor) + getlen(rem) + getlen(loop);
}
if(new_val < best) {
best = new_val;
if(rem == 0) {
ones = numints[divisor] + numints[loop];
beststring = "(" + strings[divisor] + "*" + strings[loop] + ")";
ops = numops[divisor] + numops[loop] + 1;
} else {
ones = numints[divisor] + numints[loop] + numints[rem];
beststring = "(" + strings[divisor] + "*" + strings[loop] + "+" + strings[rem] + ")";
ops = numops[divisor] + numops[loop] + numops[rem] + 2;
}
}
}
numints[i] = ones;
strings[i] = beststring;
numops[i] = ops;
}
void check_divising(const long i, const long loop, long& best, long& ones, std::string& beststring, long& ops);
void check_adding(const long i, const long loop, long& best, long& ones, std::string& beststring, long& ops);
void get_best_for_next_partial(long i)
{
if(numints[i] > 0)
return;
long best = INT_MAX; // we'll do better than this
long ones = 1;
std::string beststring = "invalid";
long ops = 1;
// Special: Try a nearby all ones
{
long loop = get_nearest_all_ones(i);
check_adding(i, loop, best, ones, beststring, ops);
}
// Special: Try nearest factorial
{
long loop = get_nearest_factorial(i);
check_adding(i, loop, best, ones, beststring, ops);
}
for(long loop = 2; loop * loop <= i; loop++)
{
check_divising(i, loop, best, ones, beststring, ops);
}
numints[i] = ones;
strings[i] = beststring;
numops[i] = ops;
}
void check_adding(const long i, const long loop, long& best, long& ones, std::string& beststring, long& ops)
{
int new_val = getlen(loop) + getlen(i - loop);
if(new_val < best) {
best = new_val;
ones = numints[loop] + numints[i - loop];
beststring = "(" + strings[loop] + "+" + strings[i - loop] + ")";
ops = numops[loop] + numops[i - loop] + 1;
}
}
void check_divising(const long i, const long loop, long& best, long& ones, std::string& beststring, long& ops)
{
long divisor = i / loop;
long rem = i - loop*divisor;
assert(rem >= 0);
int new_val;
if(rem == 0)
{
new_val = getlen(divisor) + getlen(loop);
}
else
{
new_val = getlen(divisor) + getlen(rem) + getlen(loop);
}
if(new_val < best) {
best = new_val;
if(rem == 0) {
ones = numints[divisor] + numints[loop];
beststring = "(" + strings[divisor] + "*" + strings[loop] + ")";
ops = numops[divisor] + numops[loop] + 1;
}
else {
ones = numints[divisor] + numints[loop] + numints[rem];
beststring = "(" + strings[divisor] + "*" + strings[loop] + "+" + strings[rem] + ")";
ops = numops[divisor] + numops[loop] + numops[rem] + 2;
}
}
}
long count = 0;
long countops = 0;
const int little_cutoff = 200000;
int getlen(long i)
{
if(numints[i] == 0) {
if(i < little_cutoff)
get_best_for_next_full(i);
else
get_best_for_next_partial(i);
}
if(numints[i] == 0) {
std::cout << i << " failure!" << numops[i] << ":" << strings[i] << std::endl;
exit(1);
}
return numints[i] + numops[i];
}
const std::vector<long> vals = {945536, 16878234, 32608778, 42017515, 48950830, 51483452, 52970263, 54278649, 63636656, 78817406, 89918907, 90757642, 95364861, 102706605, 113965374, 122448605, 126594161, 148064959, 150735075, 154382918, 172057472, 192280850, 194713795, 207721209, 220946392, 225230299, 227043979, 241011012, 248906099, 249796314, 250546528, 258452706, 276862988, 277140688, 280158490, 286074562, 308946627, 310972897, 322612091, 324445400, 336060042, 346729632, 349428326, 352769482, 363039453, 363851029, 392168304, 401975104, 407890409, 407971913, 425780757, 459441559, 465592122, 475898732, 482826596, 484263150, 506235403, 548951531, 554295842, 580536366, 587051904, 588265985, 588298051, 590968352, 601194306, 607771869, 618578932, 626776380, 667919873, 681786366, 689854904, 692055400, 697665495, 711608194, 734027104, 750869335, 757710567, 759967747, 777616154, 830071127, 833809927, 835873060, 836438554, 836945593, 863728236, 864158514, 871273503, 881615667, 891619600, 897181691, 918159061, 920521050, 924502226, 929983535, 943162304, 950210939, 950214176, 962610357, 974842859, 988572832};
const long biggest = 988572832;
int main(void)
{
numints.push_back(2);
strings.push_back("(1-1)");
numops.push_back(1);
numints.push_back(1);
strings.push_back("1");
numops.push_back(0);
numints.push_back(2);
strings.push_back("(1+1)");
numops.push_back(1);
numints.resize(biggest + 1);
strings.resize(biggest + 1);
numops.resize(biggest + 1);
fill_all_ones(biggest);
fill_all_factorials(biggest);
for(long i = 0; i < little_cutoff; ++i)
get_best_for_next_full(i);
for(long v : vals) {
get_best_for_next_partial(v);
std::cout << v << ":" << strings[v] << "\n";
count += numints[v];
countops += numops[v];
}
std::cout << count << ":" << countops << ":" << count * countops << "\n";
}
Результати:
945536:((1111*(1+(11+11))+(1+1))*((1+11)*(1+(1+1))+1)+1)
16878234:(((1+(1+1111))*(1+(1+(1+111)))+(11+11))*((1+11)*11+1)+(1+1))
32608778:((((((1+(1+1)))!+(111+11111))*(11*11)+111)*(1+11)+1)*(1+1))
42017515:((11)!+((((1+111)*11)*11+1)*((1+11)*(1+11)+11)))
48950830:((((11+11)*(1+11))+(11111*(1+(1+1))))*((1+111)*(1+(1+11))+1)+1)
51483452:(((1+(1+1111))*(1+111)+1)*(11+(((1+11)*11+(1+1))*(1+(1+1))))+111)
52970263:((11+((1111*11+(1+(1+1)))*(1+(1+1))))*(111*(1+(1+11))+1)+11)
54278649:((11)!+(((1+(11+(11+(11+1111))))*111+1)*(1+(1+111))+1))
63636656:((((11+111)*(1+(1+1)))*(1+111)+11)*(1+(111+((((1+(1+1)))!)!*(1+1)))))
78817406:(((((111*(11+11)+1)*(1+1))*(1+111)+111)*(1+11)+1)*(1+11)+(1+1))
89918907:(((111+((1+(1+((1+(1+1)))!)))!)*(1+1))*(1+1111)+((11*11)*(1+(1+1))))
90757642:((1111+((11+11111)*(1+1)))*(111*(11+((1+(1+(1+1))))!)+1)+(1+111))
95364861:((11)!+(((((((11+11)*11)+11111)*111)*11+(1+1))*(1+1))*(1+1)+1))
102706605:(((11)!+(((111+((11*11)*11))*(1+(((1+(1+1)))!)!))*11))*(1+1)+1)
113965374:((((111*(1+(1+(1+11))))*1111+((1+(11+11))*11+1))*11+1)*((1+(1+1)))!)
122448605:(((((1+(1+1)))!)!+((111*11)*11))*((1+(((1+(1+1)))!)!)*(1+11)+1)+(1+1))
126594161:(((((11*11)+(((1+(1+1)))!)!)*(1+111))*(1+11)+1)*(1+111)+1)
148064959:((11)!+(((111*111+(1+11))*111+1)*((1+(1+11))*((1+(1+1)))!+1)+(1+(1+1))))
150735075:(((111*111+(1+1))*(1+1111)+(1+11))*11+(1+((1+(1+1)))!))
154382918:((1111*(1+11)+1)*(((1+(11+(111+111)))*(1+1))+11111)+111)
172057472:((((((1+11)*11)*11+1)*(1+(1+1)))+11111)*(11+11111)+((1+11)*11))
192280850:(((11111*(1+11)+11)*(1+(((1+(1+1)))!)!)+(11+111))*(1+1))
194713795:((11)!+((((111+11111)*(1+(1+(1+111)))+((1+(1+1)))!)*11)*11+1))
207721209:(((111*111)*(1+(11+11))+(1+1))*(1+(1+(11+(((1+(1+1)))!)!)))+(1+(1+(1+1))))
220946392:((11)!+((((1+(1+(1+1111)))*(11+111))*111+11)*(1+11)+(1+(1+(1+1)))))
225230299:((111111111+((111*111+(1+((1+(1+1)))!))*(11+111)+(11+11)))*(1+1)+1)
227043979:((((((11+11)*11)+11111)*(1+(1+1))+1)*1111+(1+(1+1)))*((1+(1+1)))!+1)
241011012:(((11)!+((11)!+((11)!+((11+1111)*((1+111)*((1+(1+1)))!+1)))))*(1+1))
248906099:(((11111+(((((1+(1+1)))!)!*111)*(1+1)))*(1+111)+111)*(1+(1+11)))
249796314:(((11)!+(((((1+(1+1)))!)!+((1+1111)*(1+11)))*(11+111)+111))*((1+(1+1)))!)
250546528:((11)!+(((111*111)*(1+(1+(1+11)))+11)*(111*11)+(1+(11+1111))))
258452706:(((11)!+(((((1+(1+1)))!)!*((1+(1+1)))!+1)*(11+(((1+(1+1)))!)!)))*((1+(1+1)))!)
276862988:(((11+(1111*(1+1)))*(((1+(1+1)))!+1111))*111+(((1+(1+1)))!+11))
277140688:(((111*111+(1+(1+(1+(1+11)))))*(1+1))*(11+(111+11111))+(1+111))
280158490:((11)!+(((1+(111+111111))*(((1+(1+1)))!)!+(1+(1+1)))*(1+(1+1))+1))
286074562:(((11)!+((((11+1111)*(11+11))*(1+1)+1)*(1+(11+1111))))*(1+(1+1))+1)
308946627:((11)!+((((1+1111)*(((1+(1+1)))!)!+((11+11)*(1+1)))*(1+111)+1)*(1+(1+1))))
310972897:((11111*(1+(1+1))+1)*(((1111+(111*11))*(1+1))*(1+1)+1)+11)
322612091:((((((1+11)*(1+11))*(1+11)+(1+1))*111+1)*(1+111))*(1+(1+(1+(1+11))))+11)
324445400:(((1111111+(1+(1+1)))*(1+1))*((1+11)*(1+11)+(1+1))+(1+111))
336060042:(((1+1111)*(1+(11+111))+(1+111))*(11+((111*11+1)*(1+1)))+(1+1))
346729632:(((1+(1+(11111+(111*111))))*((1+111)*11+1)+(1+(1+(1+11))))*(1+11))
349428326:(((((11+11)*11)*11+1)*(1+1111)+1)*(1+(((1+(1+1)))!+111)))
352769482:(((1+11111)*(111*(11+11))+((11+111)*((1+1)*(1+1)+1)))*(1+(1+11)))
363039453:(((((1+111)*(1+111)+1)*(1+1))*(1+(1+11))+11)*(1+(1+1111)))
363851029:((((111*11+1)*1111+11)*((1+11)*11+(1+1))+(1+11))*(1+1)+1)
392168304:(((((1+(1+1111))*(1+111))*11+1)*(1+(1+11))+11)*(11+11))
401975104:(((((1+11)*(1+11)+1)*111)*111+11)*((1+111)*(1+1)+1)+(1+(1+(1+1))))
407890409:(((1+11111)*11)*((1+1111)*(1+(1+1))+1)+((1+1111)*(1+1)+1))
407971913:((11)!+((11)!+(((1+(1+11111))*(1+1)+1)*(((11+111)*11)*11+1)+(1+1111))))
425780757:(((1111+((((1+11)*11)+11111)*(1+(1+1))))*11+1)*1111+((1+(1+1)))!)
459441559:(((11111+(((1+(1+111))*(1+1)+1)*111))*111+1)*(1+(1+(1+111)))+(1+(1+11)))
465592122:(((11)!+((((1111*(11*(1+(1+1))+1)+1)*(1+(11+11)))*(1+1)+1)*111))*(1+1))
475898732:(((11)!+(((((1+111)*11+(1+1))*(1+11))*(1+1)+1)*(1+(1+111))))*11+1)
482826596:(((1+(((111*11)*11)+(11111*(1+1))))*111+1)*(11+111)+((1+(1+1)))!)
484263150:(((111*111+(1+(1+1)))*111+11)*(1+(111+((11+11)*11))))
506235403:(((1+11))!+((((1+(1+1111))*(1+1111)+((11+111)*(1+1)))*11+1)*(1+1)+1))
548951531:((((111+111)*(1+1)+1)*111+11)*11111+((11+111)*(1+11)+1))
554295842:(((1+11))!+((((1+1111)*111+1)*((1+1)*(1+1)+1))*(11+111)+(1+111)))
580536366:(((1+(111+((111*111+11)*(1+11))))*(1+111)+1)*(11+((1+(1+(1+1))))!)+11)
587051904:(((((1+1111)*(1+11))*(1+(1+1))+1)*(111*11+1)+(111*((1+(1+1)))!))*(1+11))
588265985:(((1+11))!+((1+(111+(1111*(1+(1+11)))))*((1+111)*(11*((1+(1+1)))!+1)+(1+(1+1)))))
588298051:((((((11+111)*11)*11)+(11111*(1+(1+1))))*(1+1111)+1)*11)
590968352:(((((((1+(1+1)))!)!+11111)*111+(11+11))*((1+111)*(1+1)+1)+1)*(1+1))
601194306:((((1111*(1+(1+(1+(11+111))))+1)*111+(1+1))*(1+(1+1))+1)*(1+(1+11))+11)
607771869:(((1+11))!+(((11)!+(((1111*11+1)*(1+1))*(1+(11+111))+11))*(1+(1+1))))
618578932:(((((1111*111)*11+1)*(1+1)+1)*(1+1))*(1+(1+(1+111)))+(1+111))
626776380:((((1+(1+(1+1))))!+((((1+(1+1)))!)!+(1111*111)))*(1+(11+((1+((1+(1+1)))!))!)))
667919873:((((((1+(11+111))*11+1)*111+(1+(1+1)))*1111+1)*(1+1))*(1+1)+1)
681786366:(((1+11))!+((11)!+(((11)!+((11)!+((1+(1+11111))*((1+11)*(1+11))+111)))*(1+1))))
689854904:(((11+((11111+((1+1111)*11))*(1+1)))*((11+111)*11+1)+11)*11+(1+1))
692055400:(((1+11))!+(((((1+(1+111))*(1+(1+(1+11))))*11)*11+1)*(1+(1+1111))+1))
697665495:(((1+11))!+(((((((1+(1+1)))!)!*(1+(1+(1+111)))+1)*(1+11))*(1+1)+1)*111))
711608194:(((11)!+(((1+(1+(1+(1+1111))))*(11+((11+111)*(1+1)))+(1+1))*1111))*(1+1))
734027104:(((111*(11+((1+(1+(1+1))))!)+1)*(((1+(1+1)))!+11)+1)*11111+1111)
750869335:((11111111+((1+(((1+(1+1)))!)!)*((1+11)*11+1)+1))*(11*((1+(1+1)))!+1))
757710567:((((((11+111)*11)+111111)*(1+(1+1))+1)*(1+(11+1111))+(1+(1+1)))*(1+1)+1)
759967747:(((11)!+(((1+(1+(111+11111)))*(1+(1+111)))*(1+(11+11))+1))*11)
777616154:((11111*(111+(((111*11+1)*(1+1))*(1+1)))+(11+111))*(1+(1+(1+11))))
830071127:((((1+111)*111)*((1+(1+1)))!+1)*(((1+(1+1)))!+(11+11111))+(111*(1+1)+1))
833809927:((((11+1111)*(1+1)+1)*111+1)*(1+(1+(11+(1111*(1+(1+1))))))+111)
835873060:(((((11+(111+111))*111+1)*(1+(1+111))+1)*(1+(1+11))+1)*(11+11))
836438554:(((1+11))!+(((11111*(1+1)+1)*((11+(((1+(1+1)))!)!)*11+1)+1111)*(1+1)))
836945593:(((1111*1111+(1+111))*(1+(1+111))+(1+(1+1)))*((1+(1+1)))!+1)
863728236:(((1+(1111+((11+11111)*(1+1))))*(111*111+((1+(1+1)))!))*(1+(1+1)))
864158514:(((1+11))!+(((1111*(1+(1+(1+11)))+((1+(1+1)))!)*111+1)*(111*(1+1)+1)+11))
871273503:((((1+11111)*(11+11)+1)*((1+(1+11))*(1+1)+1)+1)*((1+11)*11)+111)
881615667:((11111+((111*111+11)*(1+1)))*((111*111)*(1+1)+1)+((11+1111)*11))
891619600:(((11)!+((11)!+((((1+(11+11))*(1+1))+111111)*11)))*11+(1+(1+1)))
897181691:((11+(11+(11+((1+(1+((1+(1+1)))!)))!)))*(11+(11111*(1+1)))+((111*11+1)*11))
918159061:(((11)!+(((11+11)*11+1)*(1+(1+11))))*(1+(11+11))+(1+(1+(1+1))))
920521050:(((11)!+((((1+(11+1111))*(1+(1+(1+1111))))*(1+111)+111)*(1+(1+1))))*(1+1))
924502226:((((1111*(1+11))*(1+1)+1)*((111*(1+11)+1)*(1+1)+1))*(1+(1+11))+11)
929983535:(((11)!+((((11+111)*111+1)*111)*((1+11)*(1+1)+1)+(1+1)))*(1+11)+11)
943162304:(((11)!+((((((1+((1+(1+1)))!))!+(111*111))*111+(1+1))*(1+111))*(1+1)))*(1+1))
950210939:(((11+(111+11111))*(1+(1+(1+(((1+(1+1)))!)!)))+(1+1))*(((1+(1+1)))!+111)+(1+1))
950214176:(((11)!+((((111*111)*(1+(1+11)))*11+1)*((1+(11+111))*(1+1)+1)))*(1+1))
962610357:((((1+11))!+((1+((((1+(1+1)))!)!+(111*(1+11))))*(11+1111)+(1+111)))*(1+1)+1)
974842859:((((((11*(1+((1+(1+1)))!))+1111)*11+1)*(1+111))*((1+(1+1)))!)*111+11)
988572832:(((111111111+((11111*(1+(1+1111))+11)*11+(1+(1+1))))*(1+1))*(1+1))