• Можно ли быстрее чем за O(N) подсчитать сумму S(N,K,M) = sum i=0..N K*i%M?

    wataru
    @wataru Автор вопроса, куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Совершенно случайно наткнулся вот на это вот равнество: hermite's identity (в твитте с прикольным доказательством. Зацените).

    C помощью него наконец-то вывел способ подсчитать эти суммы за O(log n)! Я знал, что это можно сделать!

    Итак, во-первых, можно переключатся между суммами floor(i*k/m) и (i*k)%m через вот это равенство: floor(i*k/m) = (i*k - (i*k)%m) / m
    Это нам позже поможет. В сумме через floor можно сократить GCD(m, k) в них. В сумме через модуль можно сделать k %= m, если оно больше m, да и сократить полные "обороты" в n.

    Итак, можно допустить, что m > k, m >n, GCD(m, k) = 1, иначе преобразуем сумму к нужной форме и все упростим.

    Дальше, применим равенство hermite's, взяв x = i/m, n = k.

    Потом поменяем местами суммы. Под знаками суммы будет floor(i/m + t/k) (где t - новая переменная суммирования от 0 до k-1). Присмотритесь к этому выражению - там 2 числа меньших 1. Т.е. весь этот floor даст 1, только если t/k >= 1-i/m. Отсюда можно решить это неравнество, сдвинуть нижнюю границу суммирования и получить сумму единиц во внутренней сумме. Заменив ее всю на количество слагаемых там вылезает floor (t*m/k). Т.е. мы выразили сумму i*k/m через сумму t*m/k. Но мы же помним, что можно перейти к сумме модулей и там сократить множитель k в числителе. Таким образом мы вычисляем сумму для (m, k) через сумму для (k, m%k). Это точно такой же переход, как и в GCD, поэтому суммарно будет всего O(log n) итераций. Вообще, выкладки довольно нудные, ибо сумма для t*m/k будет не от 0 до какого-то n', а от n' до k-1. Но можно взять известное значение для суммы полного оборота (от 0 до k-1) и из нее вычесть сумму от 0 до n'-1. Эта сумма известна, потому что при GCD=1, она пройдется по всем остаткам в каком-то порядке.

    Формула примерно такая получается:
    FloorSum(n, k, m) = (m-1)*(k-1)/2 - (n1+1)*n1*(m/k)/2 + (n - m + 1)*(k-n1-1) - FloorSum(n1, m%k, k)
    n' = floor(((m-n)*k-1)/m)


    Вот код. Значения совпадают с тупым решением для всех чисел до 1000 и для миллиардов случайных чисел до миллиона.
    // sum i = 0.. n floor(i * k / m)
    // GCD(k, m) must be 1.
    // n < m
    // k < m
    long long FloorSumInternal(long long n, long long k, long long m) {
    	if (k == 0 || n <= 0) return 0;
    	if (m == 1) return k*n*(n+1)/2;
    	const long long n1 = ((m-n)*k - 1)/m;
    	long long ans = (m-1)*(k-1)/2 - (n1+1)*n1*(m/k)/2 + (n - m + 1)*(k-n1-1);
    	ans -=  FloorSumInternal(n1, m%k, k);
    	return ans;
    }
    
    
    // sum i = 0.. n floor(i * k / m)
    long long FloorSum(long long n, long long k, long long m) {
    	if (k == 0 || n <= 0) return 0;
    	if (m == 1) return k*n*(n+1)/2;
    
    	const long long d = Gcd(m, k);
    	m /= d;
    	k /= d;
    	if (k >= m || n >= m) {
    		// (n*k*(n+1)/2 - ModSum(n, k, m, d))/m;
    
    		const long long nn = (n+1)%m-1;
    		const long long num_full = (n+1) / m;
    		const long long kk = k % m;
    
    		long long ans = 0;
    		ans = (k*n*(n+1) - kk*(nn+1)*nn)/m - num_full * (m-1);
    		ans /= 2;
    		ans +=  FloorSumInternal(nn, kk, m);
    		return ans;
    	}
    	return FloorSumInternal(n, k, m);
    }
    
    
    
    // sum i = 0.. n (i * k) % m;
    long long ModSum(long long n, long long k, long long m)
    {
    	long long d = Gcd(k, m);
    	if (k == 0 || m == 1) return 0;
    	// (i*k) % m = i*k-floor(i*k/m)*m
    	k %= m;
    	long long num_full = (n+1) / m;
    	long long ans = num_full * (m-d) * m/2;
    	n = (n+1)%m-1;
    	if (n > 0) {
    		ans += ((long long) k)*(n+1)*n/2 - m*FloorSum(n, k/d, m/d);
    	}
    	return ans;
    }


    Правда тут есть проблема, в процессе вычисления получаются весьма большие числа. Поэтому даже если финальный ответ в long long влезает, ответ может переполнится. Но все-равно, там числа больше куба от входных значений не используются, поэтому можно в оценке сложности это не учитывать.

    Edit: прилизал код немного.
    Ответ написан
    Комментировать
  • Курсор ввода в любом месте окна браузеров?

    rus0nix
    @rus0nix
    Admin
    Видимо вы нажали клавишу F7 в Microsoft Edge.
    5b549528da25f774201802.jpeg
    Нажмите опять эту клавишу для отключения.
    Ответ написан
    19 комментариев
  • Это стрелочная функция?

    dollar
    @dollar
    Делай добро и бросай его в воду.
    Нет, это не стрелочная функция.
    Здесь нет стрелок типа такой: =>
    Ответ написан
    Комментировать
  • Как проигнорировать контейнер в контейнере?

    Aetae
    @Aetae Куратор тега JavaScript
    Тлен
    Тебе нужен event.stopPropagation(), но лучше всё-таки почитай в учебнике как работают события в javascript, там не сложно, чтоб не тратить своё время на метод тыка.
    Ответ написан
    3 комментария
  • Являются ли данные ошибки ошибками в самом деле?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега CSS
    Как относиться к таким ошибкам?
    Игнорировать и не пользоваться валидаторами вообще - они все неадекватные.
    Есть, конечно, вероятность, что у вас сборка настроена на какие-то очень древние браузеры и в реальном мире префиксы для каких-то свойств давно не нужны, а вы их добавляете, но даже в этом случае ничего плохого с вашим сайтом не произойдёт.

    Стоит ли отключить префиксы?
    Ни в коем случае.
    Ответ написан
  • Как сделать статистику в css?

    @SotickYoker
    <ul class="wrap">
      <li>
        <p>Учеников:</p>
        <p>290</p>
      </li>
      <li>
        <p>Успешно закончили курс:</p>
        <p>190</p>
      </li>
    </ul>


    ul{
      list-style-type: none;
      width: 50%;
      background: #000;
      margin: 0;
      padding: 10px;
    }
    
    li{
      display: flex;
      justify-content: space-between; 
      color: #fff;
    }


    Вот хорошая статейка - пригодится:
    https://tpverstak.ru/flex-cheatsheet/
    Ответ написан
    Комментировать
  • CSS поведение z-index?

    kryamk
    @kryamk
    И правда забавно. Вот нашёл похожий вопрос
    Ответ написан
    Комментировать
  • Как исправить ошибку?

    Нельзя модифицировать коллекцию, по которой проходишься оператором foreach
    Ответ написан
    Комментировать
  • Как приложение ASP.NET работает со множеством запросов от нескольких пользователей?

    firedragon
    @firedragon
    Не джун-мидл-сеньор, а трус-балбес-бывалый.
    Это именно для ASP .NET
    https://docs.microsoft.com/en-us/previous-versions...
    https://docs.microsoft.com/en-us/previous-versions...

    На самом деле нет. У IIS есть пул потоков сответственно из него и выбирается поток для обслуживания.

    Для net core модель немного изменилась https://www.c-sharpcorner.com/article/asp-net-core...

    https://docs.microsoft.com/ru-ru/aspnet/core/host-...
    Ответ написан
    1 комментарий
  • Как идеально построено взаимодействие между фронтэнд и бэкэнд разработчиками?

    @Vitsliputsli
    Как уже ответили, смотреть в сторону swagger.
    Но даже без него, проблемы странные. На данный момент, все выглядит так, что бек взвалил на себя работу по отладке фронта, т.е. совсем не его работу, и зашивается. А фронт вместо того, чтобы работать, плюет в потолок, спихивая вину на бек, что у того, что-то не работает.
    Чтобы протестировать ему свою работу, он вынужден разворачивать на локальной машине еще фронтэнд и билдить его каждый раз, логиниться и там тестировать как все работает. Частенько он сталкивается с проблемами, что на фронтэнде не все работает без ошибок, а ему приходится думать по вине неправильности работы api это или по другим причинам.

    Абсолютно не нужно, ни разворачивать фронт, ни думать что там не работает во фронте и по какой причине. У бека и фронта есть задача по реализации api в ней описано, как обращаться и что должен возвращать каждый метод. Соответственно, бек проверяет работоспособность api путем отправки запросов (через тот же Postman), и тесты тут будут не лишними. Если ошибка обнаруживается на фронте, то к беку летит баг, куда обращались, что получили в ответ, что ожидали получить.
    Фронтэнд... Если какая ошибка то у него работа останавливается и он пишет просто в трелло "не работает метод такой то..."

    После этого мокирует данный метод и работает дальше.
    Ответ написан
    Комментировать
  • Как идеально построено взаимодействие между фронтэнд и бэкэнд разработчиками?

    @k2lhu
    Полагаю вам нужен Swagger, пример как это выглядит в работе тут.
    Перед написание кода вы можете описать весь набор данных и их формат для обмена между бэкендом и фронтендом, и только после оформления доки приступать к работе, в этом случае бэкенду не нужен фронт, он может ориентироваться на описанную документацию сваггера, так же как и фронтед.
    Ответ написан
    4 комментария
  • Как крякнуть защищенную программу?

    saboteur_kiev
    @saboteur_kiev
    software engineer
    Перед тем как стать крякером, надо стать разработчиком.
    Научись писать программы, без этого ты не сможешь пользоваться ни декомпилятором ни дебаггером.
    Ответ написан
    Комментировать
  • Как крякнуть защищенную программу?

    @cicatrix
    было бы большой ошибкой думать
    Это отдельное направление, которое называется Реверс-инжиниринг.
    Те, кто этим занимается, это действительно, своего рода, "элита", так как там не существует готовых методик, шаблонных решений и пр. Каждая новая программа - чёрный ящик, который надо разобрать и посмотреть, как он работает, при этом ты ничего не знаешь о том, что было на уме у его создателя.
    Разумеется, любая защита обходится, но дело это кропотливое, долгое, требующее хороших знаний языка ассемблера для той линейки процессоров, под который программа написана.
    Для C# существует IL-Spy или похожие дисассемблеры, которые действительно позволяют получить некое подобие исходного кода, но, зачастую, даже имея на руках код (очень часто обфуцированный) предстоит ещё очень долгая, нудная и кропотливая работа только для того, чтобы разобраться, что там вообще происходит.
    Кряк "взлом" программы часто сводится к подмене результата проверки условия. Простой if, казалось бы. Однако найти нужное место в машинном коде или в памяти процесса - очень и очень сложно.

    Сразу говорю, что кракером быстро не становятся. На это могут потребоваться годы наряжённого труда и самообучения (помните - этому никто не сможет научить, этому можно только научиться самому), методом проб и ошибок. А каждый новый взлом - это новая задача, требующая новых знаний и совсем других подходов.
    Ответ написан
    Комментировать
  • Как крякнуть защищенную программу?

    vabka
    @vabka Куратор тега C#
    Токсичный шарпист
    Прошу не писать о декомпеляторах!

    Хорошо, буду писать только о декомпиляторах)
    Всё что нужно, чтобы обойти защиту от декомпиляции - провести обратный процесс, чтобы декомпилятор хотябы мог распознать IL и выдать валидный шарповый код.

    Когда код на руках есть - нужно уже своей головой разобраться в получившемся месиве.

    Всё делается руками, готовых решений нет.

    Я хочу стать крякером

    Не сможешь.
    Ответ написан
    Комментировать
  • Как называется такая анимация, и как ее делать вне конструкторов?

    LenovoId
    @LenovoId
    svg, css,js
    Ответ написан
    Комментировать
  • Как импортировать таблицу Excel в C#?

    FoggyFinder
    @FoggyFinder
    Существует множество библиотек для работы с Excel. Что из них выбрать зависит от задачи (например, нужно только читать данные или нужно формировать полноценный отчет, со стилями и так далее).

    Судя по описанию, здесь вам нужно только чтение, причем с поддержкой устаревшего формата xls, поэтому рекомендую библиотеку ExcelDataReader

    Если у вас .Net Core приложение не забудьте добавить строку

    Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);


    А теперь пример.

    1. В C# не принято для классов использовать публичные поля, поэтому перепишем их на свойства

    public class Questions
    {
        public string Question { get; set; }
        public string Theme { get; set; }
        public string Description { get; set; }
        public string QuestionEn { get; set; }
        public string DescrEn { get; set; }
    }


    2. Само чтение

    const string FilePath = "sample.xls";
    var qs = new List<Questions>();
    
    using var stream = File.Open(FilePath, FileMode.Open, FileAccess.Read);
    using var reader = ExcelReaderFactory.CreateReader(stream);
    do
    {
        while (reader.Read())
        {
            var question = reader.GetString(0);
            var theme = reader.GetString(1);
            var description = reader.GetString(2);
    
            qs.Add(new Questions()
            {
                Question = question,
                Theme = theme,
                Description = description
            });
        }
    } while (reader.NextResult());


    3. Выводим результат

    foreach(var q in qs)
    {
        Console.WriteLine($"{q.Question}");
        Console.WriteLine($"{q.Theme}");
        Console.WriteLine($"{q.Description}");
        Console.WriteLine(new string('-', Console.WindowWidth));
    }


    4. Запускаем, проверяем

    Индейцы в знак примирения хлопали в ладоши
    history
    Они закапывали топор войны
    ----------------------------------------------------------------------------------------------------
    Моряки пропитывали свою одежду смолой, чтобы она не рвалась
    history
    Чтобы она не пропускала воду
    ----------------------------------------------------------------------------------------------------
    Ответ написан
    1 комментарий
  • Как работать в строке с "{"?

    edward_freedom
    @edward_freedom
    Там в подсказках было, что тебе нужно продублировать фигурные скобки и отсчет начинается с 0
    Console.WriteLine("new Item{{ Thumbnail = {0} }}", item.Thumbnail);
    Ответ написан
    Комментировать
  • C# как прочитать настройки appsettings.json из любого класса?

    @OwDafuq
    Может всё-таки попробовать DI? Зачем именно "читать", когда он уже прочтен.
    Запросите в конструкторе произвольного класса IConfiguration и создавайте инстанс этого класса только через контейнер
    Ответ написан
    Комментировать