Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Поразвлечься :)

2.1K
20 октября 2011 года
disputant
95 / / 28.05.2007
Ни разу не студент, и не прошу решить задачу. Но... надеюсь, в тему.

Случайно просматривая старые "Кванты", натолкнулся в №7 за 1973 год на заметочку про автоморфные числа - там люди говорят, что написали на Минске-32 программу их расчета, и оценили, что два 45000-значных автоморфных числа и их квадраты должны считаться порядка 1.5 часов. Зацепило. Сел, набросал программу, немного пооптимизировал - получил за 19 секунд на 1.8ГГц процессоре. Получается - машина лучше того древнего Минска менее чем в 300 раз? Или это я не смог нормально написать (честно говоря, те самые часа полтора писал, на большее вдохновения не хватило :))

У кого есть свободное время и вдохновение - не хотите попробовать свои силы? :)
277
20 октября 2011 года
arrjj
1.7K / / 26.01.2011
На чем писал? Как большие числа считал? Как сравнивал?
316
20 октября 2011 года
Alm3n
889 / / 29.05.2009
А статью можно в электронном?
277
20 октября 2011 года
arrjj
1.7K / / 26.01.2011
Цитата: Alm3n
А статью можно в электронном?



Да в ней почти ничего не написано
#07 1973
#01 1973
пдф с теорией
последовательность
Вот самый простой алгоритм (на примере нахождения 25/76 376/625 0625(дада, 4-х значное с первым нулём)/9376 ...):

Код:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int amorph1=5;
int amorph2=6;
int tamorph1=amorph1;
int maxN=4;//Больше в int не влезет
for(int x=2;x<=maxN;x+=1)
for(int y=0;y<10;y+=1)
{
tamorph1=amorph1+y*pow(10,x-1);//Перебор по следствию 1.2 из теоремы 1 пдф-доки
if(int(pow(tamorph1,2))%int(pow(10,x))==tamorph1)
{
amorph1=tamorph1;
amorph2=pow(10,x)+1-tamorph1;//Всего N-значных 2 числа(теорема 2) и An+Bn=1+10^n (Торема 3)
cout<<amorph1<<" "<<amorph2<<endl;
break;
}
}
return 0;
}
2.1K
21 октября 2011 года
disputant
95 / / 28.05.2007
Цитата: arrjj
На чем писал? Как большие числа считал? Как сравнивал?



C++. Open Watcom 1.9, при компиляции в Visual C++ 2010 разница менее чем в секунду.

Сначала попробовал втупую с применением библиотеки MAPM - вышло хуже, чем у этих, в статье. Т.е. 1035 - слету, меньше секунды, но потом пошли сильные тормоза.

Тогда немного подумал - получается, что все, что надо - это сложение, умножение на цифру и на 10 в степени N... Вобщем, ни вычитания, ни умножения - ничего сложного. Набросал свой класс. Хранение числа в массиве int'ов по 8 десятичных цифр в каждом. Исходник ниже. Лучший алгоритм придумать не получается :(

Код:
/*
 * Filename: automorph.cpp
 * Created:  Thu Oct 20 2011
 * Поиск больших автоморфных чисел.
 * См. "Квант", 1973, № 7, стр. 55
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>

int LAST  = 1000;  // Сколько цифирей надо
int PRECISION;     // Сколько выделять int под большое число

// Чтоб не вычислять - берем готовое
const int tens[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
const int radix  = 100000000;

class Number   // Простой и очень ограниченный класс под нашу задачу
{
public:
    Number(int N = 0)
    {
        x = new int[PRECISION];
        memset(x,0,sizeof(int)*PRECISION);
        x[0] = N;
        n = 0;
    }
    void operator = (const Number& N)
    {
        memcpy(x,N.x,sizeof(int)*PRECISION);
        n = N.n;
    }
    ~Number() { delete[] x; }
private:
    int * x;   // Массив для представления чисел кусками по 10^8
    int   n;   // Последний задействованный элемент массива,
               // все выше - нули.
    // k-я цифра
    friend int  n_th_digit(const Number& N, int k);
    // N1 += N2
    friend void add(Number& N1, const Number& N2);
    // N += digit*10^{eex}
    friend void add(Number& N,  int digit, int eex);
    // N *= digit, digit < 10
    friend void mul(Number& N, int digit); // Не больше 10!!!
    // N *= 10^k
    friend void mul10(Number& N, int k);   // * 10^k
    // Вывод числа на stdout
    friend void out(const Number& N);
};


inline int n_th_digit(const Number& N, int k)
{
    // Ищем элемент массива
    int x = N.x[k/8];
    return (x/tens[k%8])%10;
}

inline void add(Number& N1, const Number& N2)
{
    int n = (N1.n > N2.n) ? N1.n : N2.n;
    int carry = 0;
    for(int i = 0; i <= n; ++i)
    {
        N1.x += N2.x + carry;
        if (N1.x >= radix)
        {
            carry = 1;
            N1.x -= radix;
        }
        else carry = 0;
    }
    if (carry)
    {
        N1.x[++n] = 1;
    }
    N1.n = n;
}

inline void add(Number& N,  int digit, int eex)
{
    int k = eex/8;
    digit *= tens[eex%8];
    N.x[k] += digit;
    if (N.x[k] >= radix)
    {
        N.x[k+1] += N.x[k]/radix;
        N.x[k] %= radix;
        ++k;
    }
    if (k > N.n) N.n = k;
}


inline void mul(Number& N, int d)
{
    int carry = 0;
    for(int i = 0; i <= N.n; ++i)
    {
        N.x *= d;
        N.x += carry;
        if (N.x >= radix)
        {
            carry = N.x/radix;
            N.x %= radix;
        }
        else carry = 0;
    }
    if (carry)
    {
        N.x[++N.n] = carry;
    }
}

inline void mul10(Number& N, int k) // * 10^k
{
    // сперва - сдвиг на ячейки. На сколько?
    int shift = k/8;
    if (shift)
    {
        memmove((void*)(N.x+shift),
                (const void*)N.x,(N.n+1)*sizeof(int));
        memset(&N.x[0],0,sizeof(int)*shift);
        N.n += shift;
    }
    if (k%8)
    {
        k %= 8;
        int carry = 0;
        for(int i = shift; i <= N.n; ++i)
        {
            int x = N.x;
            N.x = (x%tens[8-k])*tens[k] + carry;
            carry = x/tens[8-k];
        }
        if (carry)
        {
            N.x[++N.n] = carry;
        }
    }
}

void out(const Number& N)
{
    printf("%d",N.x[N.n]);
    for(int i = N.n-1; i>=0; --i)
        printf("%08d",N.x);
}


int main(int argc, const char * argv[])
{

    if (argc > 1)
    {
        LAST = atoi(argv[1]);
        if (LAST < 3) LAST = 1000;
    }

    PRECISION = LAST/4+10;  // С небольшим запасом...

    // Начальные значения
    Number x = 5, v = 6, y = 25, w = 36, g;
    int a, tenn = 1;

    // Засекаем время
    clock_t start = clock();
    for(int n = 1; n < LAST; ++n, tenn++)
    {
        a = n_th_digit(y,tenn);
        g = x;
        mul(g,2);
        add(g,a,tenn);
        mul(g,a);
        mul10(g,tenn);
        add(y,g);
        add(x,a,tenn);

        a = n_th_digit(w,tenn);
        if (a != 0) a = 10 - a;
        g = v;
        mul(g,2);
        add(g,a,tenn);
        mul(g,a);
        mul10(g,tenn);
        add(w,g);
        add(v,a,tenn);

        // Чтоб отслеживать, что не висим :)
        if (n%1000 == 0) {
            printf("N = %7d, %8d s\n",n,(clock()-start)/CLOCKS_PER_SEC);
        }
    }
    clock_t stop = clock();
    printf("%d s\n",(stop-start)/CLOCKS_PER_SEC);

    // Выводим числа
    out(x);
    printf("\n");
    printf("\n");
    out(v);
    printf("\n");
    printf("\n");
}
316
22 октября 2011 года
Alm3n
889 / / 29.05.2009
Первый код не работал, кстати. Сел писать свой алгоритм и лень настигла. :) Лучше уж лабораторки по шарпу пописать, там хотя бы думать не надо.
277
22 октября 2011 года
arrjj
1.7K / / 26.01.2011
Цитата: Alm3n
Первый код не работал, кстати.



Всё он работал, не надо тут вот это вот :)

316
23 октября 2011 года
Alm3n
889 / / 29.05.2009
Цитата: arrjj
Всё он работал, не надо тут вот это вот :)



Не знаю, не знаю. У меня что-то никакого вывода не было, но завершился нулём, да.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог