Cześć ktoś wie jak zapisać dzielenie modulo w rekurencji?
Zadanie: a∗b mod m
Mam zwykłe:
#include<iostream>
using namespace std;
int main()
{
long long int n,a,c;
cin>>a>>n>>c;
cout<<n%c*a%c;
return 0;
}
A czasami nie chodzi tu o wyliczenie reszty z dzielenia za pomocą rekurencji zamiast %? Coś w stylu - https://math.stackexchange.com/questions/580907/recursive-function-mod-5
Dokładnie takie zadanie:
http://solve.edu.pl/contests/download_desc/1998
Takie coś ci wyrzeźbiłem na szybko.
Twoim zadaniem jest obliczenie modulo z recmod() ...
using std::cin;
using std::cout;
long long recmod();
int counter=0;
int main() {
cout<< recmod();
return 0;
}
long long recmod() {
long long a=1;
while (counter<2) {
cout<<"Podaj "<<counter+1<<" element: ";
cin>>a;
counter++;
cout<<"\n";
a*=recmod();
}
return a;
}
i wyczyszczenie ładnie tego kodu.
Moja próba na podstawie zalinkowanego wcześniej przykładu:
#include <iostream>
#include <cmath>
int recmod(int a, int b, int m ) {
if (a*b < m) {
return a*b;
} else {
if (a>b) {
return abs(recmod(a-m, b, m));
}
else {
return abs(recmod(a,b-m,m));
}
}
}
int main() {
std::cout << recmod(2,3, 4);
std::cout<<recmod(2,21,10);
}
Edit:
Dodałem abs na wypadek(m>a || m >b).
Taki kod ale sprawdzaczka pokazuje błędne odpowiedzi :-(
#include <iostream>
#include <cmath>
long long int recmod(int a, int b, int m ) {
if (a*b < m) {
return a*b;
} else {
if (a>b) {
return abs(recmod(a-m, b, m));
}
else {
return abs(recmod(a,b-m,m));
}
}
}
int main()
{
long long int a;
long long int b;
long long int m;
std::cin>>a;
std:: cin>>b;
std::cin>>m;
std:: cout << recmod(a,b,m);
}
a * b
jest overflow.
Nie wnikam, ale coś czuje, że czepia się o
if (a*b <m)
Jak wiadomo z lekcji matematyki jeżeli a x b < m to a < m/b
if(a < m/b)
lub
if (b < m/a)
czepiać się nie powinno, bo nijak dopuszczalnych maksymalnych wartości nie przekroczy. Dodałbym też przypadek a x b = m (a = m/b), który jak wiadomo ma zwrócić 0.
Edit:
Na moje wypociny nie zwracajcie uwagi. Znalazłem przypadek. który dla a<10, b<10 i m<10 daje zły wynik.
Jest to jakiś postęp, ale dalej może być overflow w (a % m) * (b % m)
:
#include <iostream>
#include <climits>
#define ull unsigned long long int
ull recmod(ull a, ull b, ull m ) {
if (a <= LONG_LONG_MAX / b){
if (a*b < m) {
return a*b;
} else {
if (a>b) {
return recmod(a-m, b, m);
}
else {
return recmod(a,b-m,m);
}
}
}
else {
return ((a % m) * (b % m)) % m;
}
}
int main() {
std::cout << recmod(13, 5, 4) << "\n";
}
climits
?
Przy małych liczbach pewnie by wystarczyło takie coś:
#include <iostream>
int recmod(int a, int b, int m ) {
if (a*b < m) {
return a*b;
}
else {
return recmod(1, a*b-m, m);
}
}
int main() {
std::cout << recmod(5,4,7);
}
Przy większych - axb na 99.99% da overflow.
Chyba znalazłem:
https://www.geeksforgeeks.org/how-to-avoid-overflow-in-modular-multiplication/
Rozwiązanie.
Taki kod napisałem:
#include <iostream>
using namespace std;
long long p = 0, n = 0;
long long m(long long a, long long b, long long c)
{
if (b == 0) {
return 0;
}
if (b == 1) {
return a % c;
}
else {
p = b / 2;
n = m(a, p, c);
if (b % 2 == 0) {
return (n + n) % c;
}
else {
return (n + a + n) % c;
}
}
}
int main()
{
long long a, b, c;
cin >> a >> b >> c;
if (c == 1 || a == 0 || b == 0) {
cout << 0;
}
else
cout << m(a, b, c) % c;
}
%
?