Как проверить деление на 7 для большого числа в С++?

Я должен проверить, делится ли данное число на 7, что обычно делается, просто делая что-то вроде n % 7 == 0, но проблема в том, что данное число может иметь до 100000000, что не помещается даже в long long.

Другое ограничение заключается в том, что у меня всего несколько килобайт памяти, поэтому я не могу использовать массив.

Я ожидаю, что число будет на стандартном вводе, а вывод будет 1/0.

это пример

34123461273648125348912534981264376128345812354821354127346821354982135418235489162345891724592183459321864592158
0

Это должно быть возможно сделать, используя всего около 7 целочисленных переменных и cin.get(). Это также должно быть сделано с использованием только стандартных библиотек.


person Jakub Arnold    schedule 11.10.2009    source источник


Ответы (9)


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

person Paul Tomblin    schedule 11.10.2009
comment
+1: начните с концепции, что число — это просто список цифр, и вы выполняете деление каждой цифры независимо. - person D.Shawley; 11.10.2009
comment
Хотя ответы «деление на семь правил» хороши, я предпочитаю этот ответ, потому что он обобщает. - person Jeremy; 10.10.2016

вы можете использовать известное правило о делении на 7, которое гласит: сгруппируйте каждые 3 цифры вместе, начиная справа, и начните вычитать и добавлять их попеременно, делимость результата на 7 такая же, как исходное число:

ex.:

testing 341234612736481253489125349812643761283458123548213541273468213
        549821354182354891623458917245921834593218645921580

   (580-921+645-218+593-834+921-245+917-458+623-891+354-182
    +354-821+549-213+468-273+541-213+548-123+458-283+761-643
    +812-349+125-489+253-481+736-612+234-341 
    = 1882 )
    % 7 != 0 --> NOK!

есть и другие альтернативы этому правилу, и все они легко реализуемы.

person manji    schedule 11.10.2009
comment
Впервые вижу это правило, есть ссылки? - person elcuco; 11.10.2009
comment
@elcuco, это хороший трюк из модульной математики с использованием китайской теоремы об остатках. Это на самом деле работает и на 11 и 13, так как 1001 = 7 * 11 * 13. - person rlbond; 11.10.2009
comment
@rlbond Для 11 вам не нужны группы из трех цифр. Вместо этого добавьте/вычтите каждую вторую цифру. Это работает, потому что 11 делится на 11. :-) - person starblue; 12.10.2009
comment
Это хорошее правило для людей, но для компьютеров оно излишне сложно. - person starblue; 12.10.2009
comment
Хорошее решение, но как его реализовать, когда мне нужно читать ввод от начала до конца, поэтому я не могу определить, когда начинается/заканчивается первая группа? Единственный вариант, который я могу придумать, - это попробовать все три комбинации одновременно, а затем в конце определить, какая из них была правильной, но это не похоже на очень чистое решение. Я предполагаю, что нет способа прочитать ввод в обратном направлении? - person Jakub Arnold; 15.10.2009
comment
Работает ли это, если число состоит из цифр, которые не делятся на три? Как вы группируете числа, такие как 43534 и 3245434564, в группы по три? - person Qiu YU; 25.07.2020

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

person Zed    schedule 11.10.2009

Вы можете вычислить значение числа по модулю 7.

То есть для каждой цифры d и значения n вычислить n = (10 * n + d) % 7.

Это имеет то преимущество, что работает независимо от делителя 7 или основания 10.

person starblue    schedule 11.10.2009

Вы можете вычислить значение числа по модулю 7.

То есть для каждой цифры d и значения n вычислить n = (10 * n + d) % 7.

Это имеет то преимущество, что работает независимо от делителя 7 или основания 10.

Точно так же я решил эту задачу на одном из соревнований по программированию. Вот фрагмент кода, который вам нужен:

int sum = 0;
while (true) {
  char ch;
  cin>>ch;
  if (ch<'0' || ch>'9') break; // Reached the end of stdin
  sum = sum*10; // The previous sum we had must be multiplied
  sum += (int) ch;
  sum -= (int) '0'; // Remove the code to get the value of the digit
  sum %= 7; 
}

if (sum==0) cout<<"1";
else cout<<"0";

Этот код работает благодаря простым правилам модульной арифметики. Это также работает не только для 7, но и для любого делителя.

person SPIRiT_1984    schedule 21.09.2010

Я бы начал с вычитания некоторого большого числа, которое делится на 7.

Примеры чисел, которые делятся на 7, включают 700, 7000, 70000, 140000000, 42000000000 и т. д.

В конкретном примере, который вы привели, попробуйте вычесть 280000000000 (некоторое количество нулей) 0000.

Еще проще реализовать, многократно вычитая максимально возможное число, например 70000000000 (некоторое количество нулей) 0000.

person ChrisW    schedule 11.10.2009

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

Если бы у вас было меньшее число, скажем, 123, как бы вы получили из него 1, 2 и 3? Тем более, что вы работаете с основанием 10...

person Austin Hyde    schedule 11.10.2009

Н = абс

Существует простой алгоритм проверки, является ли трехзначное число кратным 7:

Замените a на x и прибавьте его к bc, где x — это десятки двузначного числа, кратного 7, сотни которого равны a.

N = 154; х = 2; 2 + 54 = 56; 7|56 и 7|154

N = 931; х = 4; 4 + 31 = 35; 7|35 и 7|931

N = 665; х = 5; 5 + 65 = 70; 7|70 и 7|665

N = 341; х = 6; 6 + 41 = 47; 7ł47 и 7ł341

Если N состоит из разных периодов, то обратную добавку результата одного периода нужно прибавить к сумме следующего периода следующим образом:

N = 341.234

6 + 41 = 47; - 41 по модулю 7 ≡ 1; 1 + 4 + 34 = 39; 7ł39 и 7łN

N = 341.234.612.736.481

Результат для 341,234 равен 39. Продолжая этот результат, мы имеем:

-39 по модулю 7 ≡ 3; 3 + 5 + 6 + 1 + 2 + 1 = 18; - 18 мод 7 ≡ 3; 3 + 0 + 36 = 39; - 39 по модулю 7 ≡ 3; 3 + 1 + 81 = 85; 7ł85 и 7łN

Это правило может быть применено полностью путем умственного расчета и очень быстро. Оно было получено из другого правила, которое я создал в версии 2.005. Он работает для чисел любой величины и для делимости на 13.

person Sivio Moura Velho    schedule 23.12.2012

Сначала возьмите это большое число в строке, а затем просуммируйте каждую цифру строки. наконец, проверьте, если (сумма% 7 == 0)

Код:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    long long int n,i,j,sum,k;
    sum=0;
    string s;
    cin>>s;
    for(i=0;i<s.length();i++)
    {
        sum=sum+(s[i]-'0');
    }

    if(sum%7==0)
    {
        printf("Yes\n");
    }
    else
    {
        printf("No\n");
    }

    return 0;
}
person Rifat iqbal shova    schedule 23.04.2016
comment
Это работает только для 9 или 3 (например, вы бы сказали, что 16 кратно 7). И если число достаточно длинное, сумма тоже переполнится. - person Teepeemm; 23.04.2016