Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/48: Рейтинг темы: голосов - 48, средняя оценка - 4.56
5 / 5 / 1
Регистрация: 30.07.2011
Сообщений: 257

Возведение в степень по модулю для чисел близких к max long long

09.01.2012, 14:20. Показов 10331. Ответов 16
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Даны числа A,B,C<=2^63-1 Надо посчитать A^B mod С.
прошу не выкладывать стандартный алгоритм для Int, так как неверный ответ в итоге получается.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.01.2012, 14:20
Ответы с готовыми решениями:

Требуется написать функцию long long pow(long long a, unsigned int p), которая возводит число a в степень p
Требуется написать функцию long long pow(long long a, unsigned int p), которая возводит число a в степень p и возвращает ap. Помогите...

Не понятный undefined reference to `unsigned long long f<unsigned long long, void>
test.cpp: #include &lt;iostream&gt; template &lt;typename FormalType, typename FactType = typename std::enable_if&lt;std::is_same&lt;FormalType,...

Несмотря на то, что переменная С имеет тип long int, возведение, к примеру, 100 в степень 5 совершается неверн
Ребят, раньше программировал ( на уровне любителя ) только на скриптовых языках с динамической типизацией (в основном JS и Python), но так...

16
3 / 3 / 0
Регистрация: 09.01.2012
Сообщений: 28
09.01.2012, 15:43
По-моему, имеет место равенство ((A^2)%C) = ((A%C)^2)%С, и это можно использовать
0
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
09.01.2012, 17:06
Цитата Сообщение от xecu91 Посмотреть сообщение
По-моему, имеет место равенство ((A^2)%C) = ((A%C)^2)%С, и это можно использовать
Идея хорошая, но при C близком к 2^64 и A<C (A%C)^2 все равно вылезет за сетку.
Может быть здесь применить китайскую теорему об остатках?
Т.е. найти 3 взаимно-простых числа < 2^32, но произведение которых > 2^64, и делать действия по их модулю, а потом результат восстановить.
Пару таких чисел могу подсказать: 2^32-1, 2^32-3
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
09.01.2012, 17:21
Тут скорее математик нужен, чем программист
0
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
09.01.2012, 17:35
Цитата Сообщение от Evg Посмотреть сообщение
Тут скорее математик нужен, чем программист

Не по теме:

А еще лучше в одном лице. Но где ж его найдешь, такого универсала. Времена Леонардо давно прошли:)

0
Эксперт С++
 Аватар для valeriikozlov
4728 / 2549 / 757
Регистрация: 18.08.2009
Сообщений: 4,568
09.01.2012, 18:02
В голову пришла одна идея, может быть не очень быстро, но точно должно считать.
Сначало нужно вычислить A^2 mod C
Вычисляем так:
A+A , если результат получился отрицательный, то всегда можно вычислить положительный результат (A+A) mod C
Итак имеем (A*2) mod C
Теперь можем вычислить (A*4) mod C
Складываем (A+A) mod C и (A+A) mod C, опять если результат отрицательный, то можем вычмслить положительный (A*4) mod C
И т.д.
Кстати промежуточные результаты можно запоминать, они еще пригодятся, если A не степень 2.
Таким образом вычислим (A^2) mod C
Имея (A^2) mod C , будем сразу вычислять (A^4) mod C, затем (A^8) mod C и т.д. Эти промежуточные результаты теперь тоже лучше запоминать, они нам тоже пригодятся, если B не степень 2.
1
114 / 114 / 13
Регистрация: 29.04.2010
Сообщений: 240
09.01.2012, 18:08
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
/* compute x^y mod m.
   assume m >= 2.
   overflow is impossible. */
int modpow(int x, int y, int m) {
  long acc = 1, z = x % m;
  while (y) {
    if (y & 1)
      acc = (acc * z) % m;
    z = (z * z) % m;
    y >>= 1;
  }
  return acc;
}
Код не мой
0
Эксперт С++
 Аватар для valeriikozlov
4728 / 2549 / 757
Регистрация: 18.08.2009
Сообщений: 4,568
09.01.2012, 18:14
PraZuBeR, не пройдет при значениях x и m близких к 2^63-1, об этом уже автор темы писал в самом начале.
0
DU
1500 / 1146 / 165
Регистрация: 05.12.2011
Сообщений: 2,279
09.01.2012, 18:27
можно попробовать решить задачу в лоб:
сделать класс для больших целых чисел негораниченного размера, реализовать для него арифметичечкие операции. ну и по тупому посчитать как для маленьких встроенных типов.
const BigInt x = A * A * A .... * A;
const BigInt result = x - x / C;
Считаться будет долго, но все таки посчитается.
0
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
09.01.2012, 18:49
Цитата Сообщение от valeriikozlov Посмотреть сообщение
В голову пришла одна идея, может быть не очень быстро, но точно должно считать.
Сначало нужно вычислить A^2 mod C
Вычисляем так:
A+A , если результат получился отрицательный, то всегда можно вычислить положительный результат (A+A) mod C
Итак имеем (A*2) mod C
Теперь можем вычислить (A*4) mod C
Складываем (A+A) mod C и (A+A) mod C, опять если результат отрицательный, то можем вычмслить положительный (A*4) mod C
И т.д.
Кстати промежуточные результаты можно запоминать, они еще пригодятся, если A не степень 2.
Таким образом вычислим (A^2) mod C
Имея (A^2) mod C , будем сразу вычислять (A^4) mod C, затем (A^8) mod C и т.д. Эти промежуточные результаты теперь тоже лучше запоминать, они нам тоже пригодятся, если B не степень 2.
Есть такой алгоритм быстрого возведения в степень (целую) Там тоже считается x^2 x^4 ...
Только тут приходится из-за больших чисел делать как бы "быстрое" умножение. Складывать-то мы можем, а умножать разрядная сетка не велит...
1
3 / 3 / 0
Регистрация: 09.01.2012
Сообщений: 28
09.01.2012, 19:48
Цитата Сообщение от xecu91 Посмотреть сообщение
По-моему, имеет место равенство ((A^2)%C) = ((A%C)^2)%С, и это можно использовать
возвращаясь к этому, по-моему можно немножко модифицировать так, чтобы (A%C)^2 не вылезло за сетку.
делаем res += A%C, пока res < 2^64, как только res >= 2^64 щёлкаем счетчиком, продолжаем до тех пор, пока не "наплюсуем" (A%C)^2 и пользуемся тем, что (X+Y)%Z = (X%Z + Y%Z)%Z
0
Эксперт С++
 Аватар для valeriikozlov
4728 / 2549 / 757
Регистрация: 18.08.2009
Сообщений: 4,568
09.01.2012, 19:53
Цитата Сообщение от Байт Посмотреть сообщение
Складывать-то мы можем, а умножать разрядная сетка не велит...
я складывать и не предлагаю. Предлагаю все через суммы, просто учитывая, что (A*A) mod C=((A mod C) * (A mod C)) mod C.
0
Диссидент
Эксперт C
 Аватар для Байт
27714 / 17332 / 3810
Регистрация: 24.12.2010
Сообщений: 38,978
09.01.2012, 21:17
А может быть все-таки обратиться за помощью к старым китайцам?
Вот, нашел 3 хороших взаимно простых числа 2^30 +1, 2^30-1, 2^30-3
0
5 / 5 / 1
Регистрация: 30.07.2011
Сообщений: 257
09.01.2012, 21:33  [ТС]
http://www.e-olimp.com/problems/252
http://www.e-olimp.com/problems/1121

Неужели никто их не решал???
0
 Аватар для Small Lamer
143 / 143 / 141
Регистрация: 05.04.2011
Сообщений: 270
09.01.2012, 21:46
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
 
using namespace std;
 
typedef long long LL;
 
#define SPR(x) ((x)*(x))
#define len(t) ((int)t.length())
#define base 10;
#define fname ""
#define sz (1000 * 1000)
#define sz2 1000
#define EPS (1e-8)
#define INF ((int)1e9 + 9)
//const double PI  = acos(-1.0);
 
LL a , b , c , ans;
 
LL mult(LL a , LL b)
{
    LL res = 0;
    while (b > 0)
    {
        if (b % 2 == 1)
        {
            b--;
            res = (res + a) % c;
            
        }
        a = (a + a) % c;
        b /= 2;
    
    }
    return res;
    
}
 
int main(){
    //freopen(fname".in", "r", stdin);
    //freopen(fname".out", "w", stdout);
 
    cin >> a >> b >> c;
    ans = 1;
    while (b > 0)
    {
        if (b % 2 == 1)
        {
            b--;
            ans = mult(ans , a);
        
        }
        b /= 2;
        a = mult(a , a);
    
    }
    cout << ans;
 
    return 0;
 
}
1
5 / 5 / 1
Регистрация: 30.07.2011
Сообщений: 257
09.01.2012, 21:56  [ТС]
Small Lamer, спасибо большое)
0
1406 / 648 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
04.02.2012, 17:32
Здесь - двоичное возведение в степень. Реализуется при помощи рекурсии или цикла. При рекурсии 3 варианта (надо a^b):
1) Если b==1, то return a;
2) Если b%2==0, то t=Stepen(a,b/2); return t*t;
3) Иначе return a*Stepen(a,b-1).
Как-то так)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
04.02.2012, 17:32
Помогаю со студенческими работами здесь

Чем различаются long long и long double?
long long или long double

Быстрое вычисление наибольшего общего делителя для unsigned long long int
Даны два числа типа unsigned long long int, в них могут оказаться любые представимые значения, требуется максимально быстро вычислить...

Сложение чисел типа long long
Пыталась сложить 2 больших числа (в пределах long long), не получилось. В чем дело? #include &lt;cmath&gt; #include &lt;cstdio&gt; ...

Написать функцию для перевода переменной типа long в символьную строку в шестнадцатиричном представлении ( ltoah( long num, char s[]) ) и тестирующую
Написать функцию для перевода переменной типа long в символьную строку в шестнадцатиричном представлении ( ltoah( long num, char s) ) и...

Меняется ответ при приведении функции pow к unsigned long long
Тест: 50 50 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
17
Ответ Создать тему
Новые блоги и статьи
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru