Ответы пользователя по тегу C++
  • Как найти из 4 чисел, где 3 равные между собой одно не равное, за один раз?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Надо уточнить - что считать, операции сравнения, или условные операторы. Считать написанные операции/операторы, или выполняющиеся.
    Возможные варианты решения:
    return a==b ? (a==c ? d : c) : (a==c ? b : a);
    int X[4];
    return X[(X[0]==X[2])+2*(X[0]==X[1])];

    int f(int p,int q,int r){
      return p==r ? q : p;
    }
    int g(int a,int b,int c,int d){
      return a==b ? f(c,d,a) : f(a,b,c);
    }

    int x=a^b,y=a^c;
    x=(x|-x)>>31; y=(y|-y)>>31;
    return ((a^b^c^d)&x&y)^((b^d)&x)^((c^d)&y)^d;

    (в последнем вообще нет сравнений и условных операторов).
    Ответ написан
    Комментировать
  • Что не так с алгоритмом для поиска наибольшей неубывающей подпоследовательности?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    В этой задаче нельзя обойтись "текущей подпоследовательностью". Надо держать самые длинные подпоследовательности, заканчивающиеся на разные элементы (чем больше элемент, тем длиннее должна быть подпоследовательность, заканчивающаяся на него), и когда приходит новый элемент, то присоединить его к самой длинной из последовательностей, к какой возможно (причём старую последовательность сразу выбрасывать нельзя - она ещё может пригодиться), а потом выбросить неоптимальные (последовательность такой же длины, что и другая, но заканчивающаяся на больший элемент).
    Например, для последовательности [1,2,7,8,9,5,6,3] вам придётся помнить
    [1,2,7,8,9]
    [1,2,5,6]
    [1,2,3]
    [1,2]
    [1]
    Любая из этих последовательностей может быть началом правильного ответа.
    Так что начало решения у вас правильное. Но в векторе d должны храниться не числа, а их индексы (и поиск должен быть более сложным), а массив prev надо модифицировать так: prev[i]=d[j-1].
    Для примера [1,2,7,8,9,5,6,3] получаем
    d={-1,0,1,7,6,4,-1,-1,-1,...}, prev={-1,0,1,2,3,1,5,1}
    (значение -1 используется для обозначения ситуации "нет такого индекса").
    Ответ написан
    3 комментария
  • Как задать массив с целыми и вещественными числами?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Не bouble, а double.
    В описании массива пишете
    double *arr2;
    а в инициализации -
    arr2=new double[n];
    Если поменять тип только в одном месте, будет ошибка.
    Ответ написан
    4 комментария
  • Как решить проблему на С++?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    А откуда взялась задача? Есть ли ссылка на оригинал? Есть ли там примеры?
    Пока впечатление, что авторы хотели чего-то другого.
    Ответ написан
    1 комментарий
  • Как обработать все случаи при решении системы линейных уравнений с двумя неизвестными?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    if (a != 0) {
                        x = e / a;
                    }
                    else {
                        x = f / a;
                    }

    Если a==0, будет деление на 0. Но, возможно, ошибки есть где-то ещё.
    Ответ написан
  • Как переводить дробные числа с двоичной системы в 10 в с++?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Можно сделать так. Завести две переменные: double x=0, y=0.
    Читать строку слева направо. Если пришла цифра b=='0' или '1', то выполнить x=2*x+b-'0'; y*=2;
    Если пришла запятая - присвоить y=1. В конце, если y ненулевой, то поделить x на y.
    Например,
    для строки 101 : x=5, y=0. Ответ 5.
    101,101 : x=45, y=8. Ответ 45/8=5.625
    101, : x=5, y=1. Ответ 5.
    ,101 : x=5, y=8. Ответ 5/8=0.625.
    Ответ написан
    1 комментарий
  • Как преобразовать определенные биты в числе?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Если номер позиции pos, число разрядов len, а число, которое надо изменить - x, то ответом будет
    x | (((1 << len) - 1) << pos)
    Ответ написан
    1 комментарий
  • Нахождение общей площади, образованной объединением прямоугольников?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Довольно просто решить за O(N^3).
    Пусть координаты k-го прямоугольника - (x1[k],x2[k],y1[k],y2[k]).
    Берёте все x1,x2 (их 2*N штук), сортируете, выкидываете одинаковые. Это проекции вершин на ось X. Обозначим полученный массив A.
    Аналогично с y1,y2 - получается массив B (тоже длиной не больше 2*N).
    Теперь перебираем прямоугольники C=[A[p],A[p+1]]*[B[q],B[q+1]] для всех p,q. Ни один из них не пересекается сторонами исходных прямоугольников, так что если центр C лежит в одном из исходных прямоугольников, то весь прямоугольник принадлежит объединению, если нет - то не имеет с ним общих внутренних точек. Суммируем площади всех прямоугольников, принадлежащих объединению, и пишем ответ.
    Можно соптимизировать до O(N^2). Насчёт O(N*log(N)) не знаю.
    Ответ написан
    6 комментариев
  • Поиск наибольшей возрастающей подпоследовательности?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Если сравнивать код с алгоритмом, то пропущено условие d[j-1] < a[i] (видимо, в коде оно должно выглядеть, как ub==v.begin() || ub[-1] < a[i] ). Похоже, что без него алгоритм будет искать не возрастающую, а неубывающую последовательность (но я в этом не уверен).
    Ответ написан
    Комментировать
  • Как решить задачу о математической игре Баше?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Если позиция сразу проигрышная, то программа не помечает ход как правильный. Больше ошибок пока не видно.
    Ответ написан
  • Как проверить делимость чисел из последовательности 1,11,111,...,11..1 на их порядковые номера?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Если N небольшое (скажем, не больше 100000), то можно так:
    char *A=new char[N+1];
      for(int n=1;n<=N;n++){
        int a=0;
        for(int b=0;b<n;b++) a=(10*a+1)%n;
        A[n]=!a;
      }

    При больших N нужно пользоваться аналогом быстрого возведения в степень.
    Получается, что кроме 3 и 37, в числах оказываются такие простые делители, как 163, 757, 1999, 9397... Не понимаю, откуда они берутся.
    UPD.
    757 - делитель 10^27-1
    163 и 9397 - делители 10^81-1
    1999 - делитель 10^999-1
    Ответ написан
    1 комментарий
  • Какая математика нужна GameDev'у?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Ведь игры это не обязательно 3D-графика?
    В зависимости от типа игр могут потребоваться:
    - вся математика, до которой сможете дотянуться
    - комбинаторика
    - теория вероятностей
    - теория графов
    - начала искусственного интеллекта
    - матан, диффуры и теоретическая механика
    - вообще ничего, кроме программирования
    Ответ написан
    Комментировать
  • Как найти 3 кратчайших пути в графе?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    В каждой вершине хранить не более трёх кратчайших путей до неё. В Дейкстре использовать очередь без модификации веса. Если очередной путь, взятый из очереди, лучше третьего по порядку пути, сохранённого в вершине, (или сохранено не более двух путей) - добавляем этот путь в вершину, а все его продолжения - в очередь.
    Проблема в том, что в путях могут появиться циклы. Например, для графа из двух вершин с тремя рёбрами
    (1,2, w=1)
    (1,2, w=3)
    (1,2, w=5)
    будут выданы пути 1-2 (по первому ребру), 1-2 (по второму ребру) и 1-2-1-2 (по первому ребру). Если циклы нежелательны - придётся возиться дольше
    Ответ написан
    Комментировать
  • Как имененить размер двумерного динамического массива?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    calloc должен заполнять нулями, это да. Но realloc не обязан заполнять нулями вновь захваченные элементы массива, это надо делать вручную.
    Ответ написан
    Комментировать
  • Как найти кратчайший путь в лабиринте?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Заведите ещё один массив и кладите в него направление, откуда пришли в данную клетку. Проще всего это направление передать параметром в FindPath. Потом пройдите по этим направлениям от финиша до старта.
    Другой вариант - на обратном проходе искать соседнюю клетку со значением tempMap на 1 меньшим, чем в данной клетке, и идти в неё. Это дольше писать и оно чуть медленнее работает, но требует меньше памяти.
    Лабиринт действительно на сетке из шестиугольников?
    Ответ написан
  • Как решать задачу на счастливые билеты?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Как-то так:

    int S0[37],S1[37],S2[37],S3[37],S4[37];
    
    void Expand(int *a,int *b,int n){
    	int s0=0;
    	for(int i=0;i<n+10;i++){
    		if(i<n) s0+=a[i];
    		if(i>=10) s0-=a[i-10];
    		b[i]=s0;
    	}
    }
    
    int Conv(int *S,int balance,int m){
    	int res=0;
    	while(--m>=0) res+=S[m]*S4[balance+m];
    	return res;
    }
    
    // number of tickets in 0..u-1
    int NHappy(int u){
    	int res=0;
    	int balance=0;
    	int digit;
    
    	digit=u/10000000; u%=10000000;
    	for(int i=0;i<digit;i++) res+=Conv(S3,balance++,28);
    	digit=u/1000000; u%=1000000;
    	for(int i=0;i<digit;i++) res+=Conv(S2,balance++,19);
    	digit=u/100000; u%=100000;
    	for(int i=0;i<digit;i++) res+=Conv(S1,balance++,10);
    	digit=u/10000; u%=10000;
    	for(int i=0;i<digit;i++) res+=S4[balance++];
    	digit=u/1000; u%=1000;
    	for(int i=0;i<digit && balance>=0;i++) res+=S3[balance--];
    	digit=u/100; u%=100;
    	for(int i=0;i<digit && balance>=0;i++) res+=S2[balance--];
    	digit=u/10; u%=10;
    	for(int i=0;i<digit && balance>=0;i++) res+=S1[balance--];
    	if(balance>=0 && balance<u) res++;
    	return res;
    }
    
    void __cdecl main(){
    	S0[0]=1;
    	Expand(S0,S1,10);
    	Expand(S1,S2,19);
    	Expand(S2,S3,28);
    	Expand(S3,S4,37);
    
    	int m,n;
    	for(;;){
    		printf("m,n: ");
    		scanf("%d%d",&m,&n);
    		printf("Result: %d\n",NHappy(99999999)+1-NHappy(m)-NHappy(99999999-n));
    	}
    }

    Проверок входных данных не делается. На простых тестах результаты были правильными. Работает, по моим оценкам, быстрее, чем за 2000 операций. Если нужно проверять много диапазонов, то можно предварительно вычислить частичные суммы Conv() в циклах, и тогда любой диапазон сосчитается за два десятка операций (и при этом не будет требовать гигабайта памяти).

    UPD: Вот оптимизированный вариант:
    int S[8][38];
    
    void InitS(){
    	for(int i=1;i<38;i++) S[0][i]=1;
    	for(int a=1;a<9;a++){
    		int s0=0;
    		for(int i=1;i<=37;i++){
    			s0+=S[a-1][i];
    			if(i>10) s0-=S[a-1][i-10];
    			S[a][i]=s0;
    		}
    	}
    }
    
    // number of tickets in 0..u-1
    int NHappy(int u){
    	int res=0;
    	int balance=36;
    	for(int a=7,b=10000000;a>=0;a--,b/=10){
    		int digit=u/b;
    		u%=b;
    		int b1;
    		if(a>3){
    			balance-=9;
    			res+=S[a][b1=balance+digit]-S[a][balance];
    		} else{
    			b1=balance-digit; if(b1<0) b1=-1;
    			res+=S[a][balance+1]-S[a][b1+1];
    		}
    		balance=b1;
    	}
    	return res;
    }
    
    void __cdecl main(){
    	InitS();
    	int m,n;
    	for(;;){
    		printf("m,n: ");
    		scanf("%d%d",&m,&n);
    		printf("Result: %d\n",NHappy(99999999)+1-NHappy(m)-NHappy(99999999-n));
    	}
    }

    Не спрашивайте, почему :)
    Ответ написан
    3 комментария
  • Как правильно закодить раскраску графа в с++?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Рекурсией. Находите нераскрашенную вершину, у которой меньше всего вариантов раскраски, и красите её во все возможные цвета. После каждой покраски - рекурсивно вызываете эту же функцию. Если оказалось, что неиспользованных цветов столько же, сколько нераскрашенных вершин - красите каждую в отдельный цвет и возвращаете как решение.
    Ответ написан
    Комментировать
  • Как написать функцию удаления лишних пробелов в строке?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Лишние пробелы - это те, которых больше одного подряд?
    List *delSpaces(List *p) {
        for(List **a=&p;*a;){
            if((*a)->c==' ' && (*a)->next && (*a)->next->c==' ') *a=(*a)->next;
            else a=&((*a)->next);
        }
        return p;
    }

    Не проверялось.
    Ответ написан
  • Как составить алгоритм решения задачи на ДП или Рекурсию (Задача на лесенку)?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Решить задачу легко - заводите массив A[N,N], в каждой клетке [K,M] которого будет записано число лесенок из K кубиков, нижний слой которых состоит из M кубиков. Число будет ненулевым, когда M <= K <= M*(M+1)/2.
    Массив заполняется начиная со строчки K=1 по формуле A[K,M]=sum(A[K-M,r],r=1..M-1). Сумма элементов в строчке K=N будет искомым числом.

    В решении, ссылку на которое вы дали, последовательно вычисляется число лестниц из j кубиков, нижний ряд которых не длиннее, чем i кубиков. Чтобы найти это число, надо к уже найденным лестницам, нижний ряд которых не длиннее, чем i-1 кубик (их мы оставляем без изменения), прибавить лестницы из j-i кубиков с нижним рядом не длиннее, чем i-1 кубик (к ним мы добавим ряд из i кубиков). Что и делается во внутреннем цикле.
    Ответ написан
    5 комментариев
  • Как верно реализовать внешнюю сортировку естественным слиянием с порогом?

    Mrrl
    @Mrrl
    Заводчик кардиганов
    Не очень понятно, зачем здесь Z. Если 1000 структур помещается в памяти, и мы их можем отсортировать, то казалось бы - читаем из файла 10 раз по 1000 структур (по порядку, за один проход), каждый раз структуры сортируем и в отсортированном порядке помещаем в новый файл. Всего получается 10 файлов. Дальше - обычный merge. Кстати, слить можно сразу все 10 файлов, если их можно открыть одновременно. Если нет - сливаем два самых маленьких файла, пока не останется один (выгодно, чтобы сливаемые файлы были примерно одинакового размера - как группы символов в коде Хаффмана).
    Возможно, Z придумали, чтобы файлы были не совсем одинаковыми, чтобы алгоритм не закладывался на одинаковость размера. Но тогда лучше было бы, например, "случайное число от 500 до 1000". В любом случае, если брать не максимум, то алгоритму только хуже.
    Ответ написан
    Комментировать