Предложите и обоснуйте эффективный алгоритм для проверки делимости большого целого числа на 9 и на 11, объясните, когда и почему эти правила работают, и предложите обобщение для других оснований счисления
Алгоритм для 9 Правило: целое число делится на 999 тогда и только тогда, когда сумма его цифр делится на 999. Почему это работает: для основания десять 10≡1(mod9)10\equiv 1\pmod{9}10≡1(mod9), значит для числа NNN с цифрами did_idi (единицы — d0d_0d0) имеем N=∑i≥0di10i≡∑i≥0di(mod9).
N=\sum_{i\ge0} d_i 10^i \equiv \sum_{i\ge0} d_i \pmod{9}. N=i≥0∑di10i≡i≥0∑di(mod9).
Поэтому проверка сводится к вычислению суммы цифр по модулю 999. Эффективный алгоритм (стриминг, не требует хранения всего числа): 1. Инициализировать r:=0r:=0r:=0. 2. Для каждой цифры ddd (с любой стороны): r:=(r+d) mod 9r:= (r + d) \bmod 9r:=(r+d)mod9. 3. В конце NNN делится на 999 тогда и только тогда, когда r=0r=0r=0. Сложность: O(n)O(n)O(n) по числу цифр, память O(1)O(1)O(1). Можно ускорять объединением блоков цифр (читая, скажем, по 9 цифр и беря число по модулю 999), но принцип тот же. Алгоритм для 11 Правило: NNN делится на 111111 тогда и только тогда, когда альтернирующая сумма цифр делится на 111111 (т. е. разность сумм цифр на чётных и нечётных позициях равна 000 по модулю 111111). Почему это работает: 10≡−1(mod11)10\equiv -1\pmod{11}10≡−1(mod11), поэтому N=∑i≥0di10i≡∑i≥0di(−1)i(mod11).
N=\sum_{i\ge0} d_i 10^i \equiv \sum_{i\ge0} d_i(-1)^i \pmod{11}. N=i≥0∑di10i≡i≥0∑di(−1)i(mod11). Эффективный алгоритм: 1. Инициализировать r:=0r:=0r:=0, знак s:=1s:=1s:=1. 2. Для каждой цифры ddd (идя от младших к старшим или наоборот, просто чередовать знак): r:=(r+s⋅d) mod 11r:= (r + s\cdot d) \bmod 11r:=(r+s⋅d)mod11, затем s:=−ss:=-ss:=−s. 3. В конце NNN делится на 111111 тогда и только тогда, когда r≡0r\equiv 0r≡0. Альтернатива (универсальный приём): использовать накопление по основанию: r:=(r⋅10+d) mod 11
r:= (r\cdot 10 + d)\bmod 11 r:=(r⋅10+d)mod11
для последовательного чтения цифр слева направо; в конце проверить r=0r=0r=0. Это тоже работает и обычно наиболее просто реализуется. Обобщение для других оснований и модулей Общий факт: для основания счисления bbb и модуля mmm положим r≡b mod mr\equiv b\bmod mr≡bmodm. Тогда для числа N=∑i≥0dibi
N=\sum_{i\ge0} d_i b^i N=i≥0∑dibi
имеем N≡∑i≥0diri(modm).
N\equiv \sum_{i\ge0} d_i r^i \pmod m. N≡i≥0∑diri(modm).
Следствия: - Если r≡1(modm)r\equiv 1\pmod mr≡1(modm) (т. е. m∣(b−1)m\mid (b-1)m∣(b−1)), то тест сводится к сумме цифр по модулю mmm (аналог правила для 333 и 999 при b=10b=10b=10). - Если r≡−1(modm)r\equiv -1\pmod mr≡−1(modm) (т. е. m∣(b+1)m\mid (b+1)m∣(b+1)), то тест сводится к альтернирующей сумме цифр (аналог для 111111). - В общем случае порядок элемента rrr по модулю mmm равен некоторому ttt; тогда веса rir^iri периодичны с периодом ttt, и проверка сводится к взвешенной сумме по блокам длины ttt. Универсальный и эффективный алгоритм для любого mmm: вычислять остаток по модулю mmm методом Горнера по основанию bbb: 1. r:=0r:=0r:=0. 2. Для каждой цифры ddd слева направо: r:=(r⋅b+d) mod mr:= (r\cdot b + d)\bmod mr:=(r⋅b+d)modm. 3. Число делится на mmm тогда и только тогда, когда r=0r=0r=0. Сложность этого алгоритма O(n)O(n)O(n) по числу цифр, память O(1)O(1)O(1). Он работает для любых b,mb,mb,m (не требуется взаимной простоты), и является практической реализацией всех частных правил, которые получаются при специальных значениях rrr.
Правило: целое число делится на 999 тогда и только тогда, когда сумма его цифр делится на 999.
Почему это работает: для основания десять 10≡1(mod9)10\equiv 1\pmod{9}10≡1(mod9), значит для числа NNN с цифрами did_idi (единицы — d0d_0d0 ) имеем
N=∑i≥0di10i≡∑i≥0di(mod9). N=\sum_{i\ge0} d_i 10^i \equiv \sum_{i\ge0} d_i \pmod{9}.
N=i≥0∑ di 10i≡i≥0∑ di (mod9). Поэтому проверка сводится к вычислению суммы цифр по модулю 999.
Эффективный алгоритм (стриминг, не требует хранения всего числа):
1. Инициализировать r:=0r:=0r:=0.
2. Для каждой цифры ddd (с любой стороны): r:=(r+d) mod 9r:= (r + d) \bmod 9r:=(r+d)mod9.
3. В конце NNN делится на 999 тогда и только тогда, когда r=0r=0r=0.
Сложность: O(n)O(n)O(n) по числу цифр, память O(1)O(1)O(1). Можно ускорять объединением блоков цифр (читая, скажем, по 9 цифр и беря число по модулю 999), но принцип тот же.
Алгоритм для 11
Правило: NNN делится на 111111 тогда и только тогда, когда альтернирующая сумма цифр делится на 111111 (т. е. разность сумм цифр на чётных и нечётных позициях равна 000 по модулю 111111).
Почему это работает: 10≡−1(mod11)10\equiv -1\pmod{11}10≡−1(mod11), поэтому
N=∑i≥0di10i≡∑i≥0di(−1)i(mod11). N=\sum_{i\ge0} d_i 10^i \equiv \sum_{i\ge0} d_i(-1)^i \pmod{11}.
N=i≥0∑ di 10i≡i≥0∑ di (−1)i(mod11).
Эффективный алгоритм:
1. Инициализировать r:=0r:=0r:=0, знак s:=1s:=1s:=1.
2. Для каждой цифры ddd (идя от младших к старшим или наоборот, просто чередовать знак): r:=(r+s⋅d) mod 11r:= (r + s\cdot d) \bmod 11r:=(r+s⋅d)mod11, затем s:=−ss:=-ss:=−s.
3. В конце NNN делится на 111111 тогда и только тогда, когда r≡0r\equiv 0r≡0.
Альтернатива (универсальный приём): использовать накопление по основанию:
r:=(r⋅10+d) mod 11 r:= (r\cdot 10 + d)\bmod 11
r:=(r⋅10+d)mod11 для последовательного чтения цифр слева направо; в конце проверить r=0r=0r=0. Это тоже работает и обычно наиболее просто реализуется.
Обобщение для других оснований и модулей
Общий факт: для основания счисления bbb и модуля mmm положим r≡b mod mr\equiv b\bmod mr≡bmodm. Тогда для числа
N=∑i≥0dibi N=\sum_{i\ge0} d_i b^i
N=i≥0∑ di bi имеем
N≡∑i≥0diri(modm). N\equiv \sum_{i\ge0} d_i r^i \pmod m.
N≡i≥0∑ di ri(modm). Следствия:
- Если r≡1(modm)r\equiv 1\pmod mr≡1(modm) (т. е. m∣(b−1)m\mid (b-1)m∣(b−1)), то тест сводится к сумме цифр по модулю mmm (аналог правила для 333 и 999 при b=10b=10b=10).
- Если r≡−1(modm)r\equiv -1\pmod mr≡−1(modm) (т. е. m∣(b+1)m\mid (b+1)m∣(b+1)), то тест сводится к альтернирующей сумме цифр (аналог для 111111).
- В общем случае порядок элемента rrr по модулю mmm равен некоторому ttt; тогда веса rir^iri периодичны с периодом ttt, и проверка сводится к взвешенной сумме по блокам длины ttt.
Универсальный и эффективный алгоритм для любого mmm: вычислять остаток по модулю mmm методом Горнера по основанию bbb:
1. r:=0r:=0r:=0.
2. Для каждой цифры ddd слева направо: r:=(r⋅b+d) mod mr:= (r\cdot b + d)\bmod mr:=(r⋅b+d)modm.
3. Число делится на mmm тогда и только тогда, когда r=0r=0r=0.
Сложность этого алгоритма O(n)O(n)O(n) по числу цифр, память O(1)O(1)O(1). Он работает для любых b,mb,mb,m (не требуется взаимной простоты), и является практической реализацией всех частных правил, которые получаются при специальных значениях rrr.