@@ -36,52 +36,38 @@ pub fn funkcia(a: i64, b: i64) -> u64 {
3636 let g = gcd_nodiv ( a, b) ;
3737 debug_assert ! ( g % 2 == 1 ) ;
3838
39- if g > 1 {
40- debug_assert ! ( a % g == 0 ) ;
41- debug_assert ! ( b % g == 0 ) ;
42- // remove common factors with exponent 1
43- a = a / g;
44- b = b / g;
45- debug_assert ! ( a % 2 == 1 && b % 2 == 1 ) ;
46-
47- // if factor in a has higher exponent than in b, we need to divide a again by that factor
48- // so we find the remaining common prime factors in a, and divide them out
49- loop {
50- let a_rem = gcd_nodiv ( a, g) ; // get remaining prime factors of a
51- if a_rem == 1 {
52- break ;
53- }
54- debug_assert ! ( a % a_rem == 0 ) ;
55- a /= a_rem;
56- }
57- // and the same for b
58- loop {
59- let b_rem = gcd_nodiv ( b, g) ; // get remaining prime factors of b
60- if b_rem == 1 {
61- break ;
62- }
63- debug_assert ! ( b % b_rem == 0 ) ;
64- b /= b_rem;
65- }
39+ // g contains all common factors multiplied together (with some exponent)
40+ // we need to repeatedly divide `a` by the remaining factors from `g`
41+ // the remaining factors are found by `gcd(a / g, g)`
42+ let mut a_rem = g;
43+ while a_rem > 1 {
44+ a = a / a_rem;
45+ a_rem = gcd_nodiv ( a, a_rem) ; // get remaining prime factors of a
46+ }
47+ // and the same for b
48+ let mut b_rem = g;
49+ while b_rem > 1 {
50+ b /= b_rem;
51+ b_rem = gcd_nodiv ( b, b_rem) ; // get remaining prime factors of b
6652 }
6753
6854 debug_assert ! ( gcd( a, b) == 1 ) ;
69- if a == b && prime_2_exp == 0 {
55+ if a == b && prime_2_exp == 0 { // a == b means that both are 1, because they cannot have common divisors
7056 return 0 ; // Pokiaľ je množina prvočísel prázdna, výsledkom je nula
7157 }
7258
7359 // Result is simply (a * b * 2^prime_2_exp) % MOD
7460 // We just need to be careful about i64 overflow (and minimizing number of modulos)
7561 if let Some ( result) = a. checked_mul ( b) {
76- if result < MOD >> prime_2_exp {
62+ if result < ( MOD >> prime_2_exp) {
7763 // no overflow
7864 debug_assert ! ( result. checked_mul( 1 << prime_2_exp) . unwrap( ) < MOD ) ;
7965 result << prime_2_exp
80- } else if prime_2_exp < 30 {
66+ } else if prime_2_exp < MOD . leading_zeros ( ) {
8167 debug_assert ! ( ( result % MOD ) . checked_mul( 1 << prime_2_exp) . is_some( ) ) ;
8268 ( ( result % MOD ) << prime_2_exp) % MOD
8369 } else {
84- ( result % MOD ) . checked_mul ( ( 1 << prime_2_exp) % MOD ) . unwrap ( ) % MOD
70+ ( ( result % MOD ) * ( ( 1 << prime_2_exp) % MOD ) ) % MOD
8571 }
8672 } else {
8773 let a2 = a % MOD ;
@@ -123,6 +109,7 @@ fn gcd_nodiv(mut a: u64, mut b: u64) -> u64 {
123109 }
124110
125111 debug_assert_eq ! ( a, gcd( a_orig, b_orig) , "a_orig = {a_orig}, b_orig = {b_orig}" ) ;
112+ debug_assert ! ( a_orig % a == 0 ) ;
126113
127114 a
128115}
0 commit comments