I am trying to solve a programming problem where I have to calculate the prime factorization of any integer up to 2^63-1 (a long long int in C++). I am using Shank's Square Forms Factorization (SQUFOF) to calculate de divisors, but the problem is in some cases SQUFOF fails to find any divisor. here is the implemented code in C++:
typedef unsigned long long int lli;
lli LLIMAX=9223372036854775807ULL;
lli mult[16]={1ULL,3ULL,5ULL,7ULL,11ULL,15ULL,21ULL,33ULL,35ULL,55ULL,77ULL,105ULL,165ULL,231ULL,385ULL,1155ULL};
lli SQUFOF( lli N ) {
lli D, Po, P, Pprev, Q, Qprev, q, b, r, s;
int L, B, i;
if (isSquare(N)) {
return (lli)round(sqrt((double)ni));
}
for (int k = 0; k < 16 && N <= LLIMAX/mult[k]; k++) {
D = mult[k]*N;
Po = Pprev = P = (lli)floor(sqrt((double)D));
Qprev = 1ULL;
Q = D - Po*Po;
if (Q==0LL) {return mult[k];}
L = 2 * ((int)floor(sqrt(2.0*round(sqrt((double)N)))));
B = 3 * L;
for (i = 2 ; i < B ; i++) {
b = (Po + P)/Q;
P = b*Q - P;
q = Q;
Q = Qprev + b*(Pprev - P);
if (!(i & 1) && isSquare(Q)) break;
Qprev = q;
Pprev = P;
};
if (i >= B) continue;
r = (lli)round(sqrt((double)Q));
b = (Po - P)/r;
Pprev = P = b*r + P;
Qprev = r;
Q = (D - Pprev*Pprev)/Qprev;
i = 0;
do {
b = (Po + P)/Q;
Pprev = P;
P = b*Q - P;
q = Q;
Q = Qprev + b*(Pprev - P);
Qprev = q;
i++;
} while (P != Pprev);
r = gcd(N, Qprev);
if (r != 1ULL && r != N) return r;
}
return 0ULL;
}
I use the deterministic Miller-Rabin test to ensure N is not a prime number before calling the function. I would like to know if SQUFOF can successfully find non-trivial factors of any composite number up to 2^63-1, and in such case I would like to know what are the problems of my code too. Thanks.
EDIT: It is not neccesary for me to find any errors on my code, it would be enough if someone could provide a C++ implementation of SQUFOF confirmed to be able to successfully extract non-trivial factors for integers up to 2^63-1. Thanks again.
Problem statement : Given two integers n and m, output Fn mod m (that is, the remainder of Fn when divided by m).
Input Format. The input consists of two integers n and m given on the same line (separated by a space).
Constraints. 1 ≤ n ≤ 10^18, 2 ≤ m ≤ 10^5
Output Format. Output Fn mod m.
I tried the following program and it didn't work. The method pi is returning the right Pisano period though for any number as per http://webspace.ship.edu/msrenault/fibonacci/fiblist.htm
#include <iostream>
long long pi(long long m) {
long long result = 2;
for (long long fn2 = 1, fn1 = 2 % m, fn = 3 % m;
fn1 != 1 || fn != 1;
fn2 = fn1, fn1 = fn, fn = (fn1 + fn2) % m
) {
result++;
}
return result;
}
long long get_fibonaccihuge(long long n, long long m) {
long long periodlength = pi(m);
int patternRemainder = n % periodlength;
long long *sum = new long long[patternRemainder];
sum[0] = 0;
sum[1] = 1;
for (int i = 2; i <= patternRemainder; ++i)
{
sum[i] = sum[i - 1] + sum[i - 2];
}
return sum[patternRemainder] % m;
}
int main() {
long long n, m;
std::cin >> n >> m;
std::cout << get_fibonaccihuge(n, m) << '\n';
}
The exact program/logic is working well in python as expected. What's wrong withthis cpp program ? Is it the data types ?
Performing 10^18 additions isn't going to be very practical. Even on a teraflop computer, 10^6 seconds is still 277 hours.
But 10^18 ~= 2^59.8 so there'll be up to 60 halving steps.
Calculate (a,b) --> (a^2 + b^2, 2ab + b^2) to go from (n-1,n)th to (2n-1,2n)th consecutive Fibonacci number pairs in one step.
At each step perform the modulus calculation for each operation. You'll need to accommodate integers up to 3*1010 ≤ 235 in magnitude (i.e. up to 35 bits).
(cf. a related older answer of mine).
This was my solution for this problem, it works well and succeeded in the submission test ...
i used a simpler way to get the pisoano period ( pisano period is the main tricky part in this problem ) ... i wish to be helpful
#include <iostream>
using namespace std;
unsigned long long get_fibonacci_huge_naive(unsigned long long n, unsigned long long m)
{
if (n <= 1)
return n;
unsigned long long previous = 0;
unsigned long long current = 1;
for (unsigned long long i = 0; i < n - 1; ++i)
{
unsigned long long tmp_previous = previous;
previous = current;
current = tmp_previous + current;
}
return current % m;
}
long long get_pisano_period(long long m)
{
long long a = 0, b = 1, c = a + b;
for (int i = 0; i < m * m; i++)
{
c = (a + b) % m;
a = b;
b = c;
if (a == 0 && b == 1)
{
return i + 1;
}
}
}
unsigned long long get_fibonacci_huge_faster(unsigned long long n, unsigned long long m)
{
n = n % get_pisano_period(m);
unsigned long long F[n + 1] = {};
F[0] = 0;
F[-1] = 1;
for (int i = 1; i <= n; i++)
{
F[i] = F[i - 1] + F[i - 2];
F[i] = F[i] % m;
}
return F[n];
}
int main()
{
unsigned long long n, m;
std::cin >> n >> m;
std::cout << get_fibonacci_huge_faster(n, m) << '\n';
}
I have the function below to calculate the modular multiplicative inverse of a number n given the modulo number p.
int modInverse(int n, int p) {
n %= p;
for(int x = 1; x < p; x++) {
if((n*x) % p == 1) return x;
}
}
If n is positive, it wokrs fine, but if n is negative it gives always 0.
How can I fix it?
Multiplicative inverse of x mod n: x^-1 mod n, is the number that must be multiplied by x to get 1 mod n
e.g. 3^-1 mod 7 = 5, since 3 * 5 = 1 mod 7
example code:
int modulo(int n, int p)
{
int r = n%p;
if(((p > 0) && (r < 0)) || ((p < 0) && (r > 0)))
r += p;
return r;
}
int modInverse(int n, int p) {
n = modulo(n, p);
for(int x = 1; x < p; x++) {
if(modulo(n*x, p) == 1) return x;
}
return 0;
}
int main(void)
{
int r;
r = modInverse(-25, 7);
return 0;
}
if you wanted a quotient and a remainder:
void divmod(int n, int p, int &q, int &r)
{
q = n/p;
r = n%p;
if(((p > 0) && (r < 0)) || ((p < 0) && (r > 0))){
q -= 1;
r += p;
}
}
Besides unnecessary iterations, the method you are using has a O(p) complexity. You may want to use the Extended Euclidean Algorithm with a O(log(p)) complexity. Anyway, answering to your question and the way you're doing it, I'd suggest you try this approach, which reduces the number of iterations: (Java)
int calculateInverse2(int a, int zp) {
for (int i = (int) Math.ceil((zp-1)/a); i < zp; i++) {
if (Math.floorMod(a*i,zp) == 1) return i;
}
return -1;
}
Related to negative values in modulo operation, depends upon the language. Try to implement a method which sums certain times p to establish the number within the integer ring.
Example:
(-7)mod(2) => (-7+2)mod(2) => (-7+2+2)mod(2) => (-7+2+2+2)mod(6) => (-7+2+2+2+2)mod(6) => (1)mod(7)=1
Easy to compute.
What I mean by "large n" is something in the millions. p is prime.
I've tried
http://apps.topcoder.com/wiki/display/tc/SRM+467
But the function seems to be incorrect (I tested it with 144 choose 6 mod 5 and it gives me 0 when it should give me 2)
I've tried
http://online-judge.uva.es/board/viewtopic.php?f=22&t=42690
But I don't understand it fully
I've also made a memoized recursive function that uses the logic (combinations(n-1, k-1, p)%p + combinations(n-1, k, p)%p) but it gives me stack overflow problems because n is large
I've tried Lucas Theorem but it appears to be either slow or inaccurate.
All I'm trying to do is create a fast/accurate n choose k mod p for large n. If anyone could help show me a good implementation for this I'd be very grateful. Thanks.
As requested, the memoized version that hits stack overflows for large n:
std::map<std::pair<long long, long long>, long long> memo;
long long combinations(long long n, long long k, long long p){
if (n < k) return 0;
if (0 == n) return 0;
if (0 == k) return 1;
if (n == k) return 1;
if (1 == k) return n;
map<std::pair<long long, long long>, long long>::iterator it;
if((it = memo.find(std::make_pair(n, k))) != memo.end()) {
return it->second;
}
else
{
long long value = (combinations(n-1, k-1,p)%p + combinations(n-1, k,p)%p)%p;
memo.insert(std::make_pair(std::make_pair(n, k), value));
return value;
}
}
So, here is how you can solve your problem.
Of course you know the formula:
comb(n,k) = n!/(k!*(n-k)!) = (n*(n-1)*...(n-k+1))/k!
(See http://en.wikipedia.org/wiki/Binomial_coefficient#Computing_the_value_of_binomial_coefficients)
You know how to compute the numerator:
long long res = 1;
for (long long i = n; i > n- k; --i) {
res = (res * i) % p;
}
Now, as p is prime the reciprocal of each integer that is coprime with p is well defined i.e. a-1 can be found. And this can be done using Fermat's theorem ap-1=1(mod p) => a*ap-2=1(mod p) and so a-1=ap-2.
Now all you need to do is to implement fast exponentiation(for example using the binary method):
long long degree(long long a, long long k, long long p) {
long long res = 1;
long long cur = a;
while (k) {
if (k % 2) {
res = (res * cur) % p;
}
k /= 2;
cur = (cur * cur) % p;
}
return res;
}
And now you can add the denominator to our result:
long long res = 1;
for (long long i = 1; i <= k; ++i) {
res = (res * degree(i, p- 2)) % p;
}
Please note I am using long long everywhere to avoid type overflow. Of course you don't need to do k exponentiations - you can compute k!(mod p) and then divide only once:
long long denom = 1;
for (long long i = 1; i <= k; ++i) {
denom = (denom * i) % p;
}
res = (res * degree(denom, p- 2)) % p;
EDIT: as per #dbaupp's comment if k >= p the k! will be equal to 0 modulo p and (k!)^-1 will not be defined. To avoid that first compute the degree with which p is in n*(n-1)...(n-k+1) and in k! and compare them:
int get_degree(long long n, long long p) { // returns the degree with which p is in n!
int degree_num = 0;
long long u = p;
long long temp = n;
while (u <= temp) {
degree_num += temp / u;
u *= p;
}
return degree_num;
}
long long combinations(int n, int k, long long p) {
int num_degree = get_degree(n, p) - get_degree(n - k, p);
int den_degree = get_degree(k, p);
if (num_degree > den_degree) {
return 0;
}
long long res = 1;
for (long long i = n; i > n - k; --i) {
long long ti = i;
while(ti % p == 0) {
ti /= p;
}
res = (res * ti) % p;
}
for (long long i = 1; i <= k; ++i) {
long long ti = i;
while(ti % p == 0) {
ti /= p;
}
res = (res * degree(ti, p-2, p)) % p;
}
return res;
}
EDIT: There is one more optimization that can be added to the solution above - instead of computing the inverse number of each multiple in k!, we can compute k!(mod p) and then compute the inverse of that number. Thus we have to pay the logarithm for the exponentiation only once. Of course again we have to discard the p divisors of each multiple. We only have to change the last loop with this:
long long denom = 1;
for (long long i = 1; i <= k; ++i) {
long long ti = i;
while(ti % p == 0) {
ti /= p;
}
denom = (denom * ti) % p;
}
res = (res * degree(denom, p-2, p)) % p;
For large k, we can reduce the work significantly by exploiting two fundamental facts:
If p is a prime, the exponent of p in the prime factorisation of n! is given by (n - s_p(n)) / (p-1), where s_p(n) is the sum of the digits of n in the base p representation (so for p = 2, it's popcount). Thus the exponent of p in the prime factorisation of choose(n,k) is (s_p(k) + s_p(n-k) - s_p(n)) / (p-1), in particular, it is zero if and only if the addition k + (n-k) has no carry when performed in base p (the exponent is the number of carries).
Wilson's theorem: p is a prime, if and only if (p-1)! ≡ (-1) (mod p).
The exponent of p in the factorisation of n! is usually calculated by
long long factorial_exponent(long long n, long long p)
{
long long ex = 0;
do
{
n /= p;
ex += n;
}while(n > 0);
return ex;
}
The check for divisibility of choose(n,k) by p is not strictly necessary, but it's reasonable to have that first, since it will often be the case, and then it's less work:
long long choose_mod(long long n, long long k, long long p)
{
// We deal with the trivial cases first
if (k < 0 || n < k) return 0;
if (k == 0 || k == n) return 1;
// Now check whether choose(n,k) is divisible by p
if (factorial_exponent(n) > factorial_exponent(k) + factorial_exponent(n-k)) return 0;
// If it's not divisible, do the generic work
return choose_mod_one(n,k,p);
}
Now let us take a closer look at n!. We separate the numbers ≤ n into the multiples of p and the numbers coprime to p. With
n = q*p + r, 0 ≤ r < p
The multiples of p contribute p^q * q!. The numbers coprime to p contribute the product of (j*p + k), 1 ≤ k < p for 0 ≤ j < q, and the product of (q*p + k), 1 ≤ k ≤ r.
For the numbers coprime to p we will only be interested in the contribution modulo p. Each of the full runs j*p + k, 1 ≤ k < p is congruent to (p-1)! modulo p, so altogether they produce a contribution of (-1)^q modulo p. The last (possibly) incomplete run produces r! modulo p.
So if we write
n = a*p + A
k = b*p + B
n-k = c*p + C
we get
choose(n,k) = p^a * a!/ (p^b * b! * p^c * c!) * cop(a,A) / (cop(b,B) * cop(c,C))
where cop(m,r) is the product of all numbers coprime to p which are ≤ m*p + r.
There are two possibilities, a = b + c and A = B + C, or a = b + c + 1 and A = B + C - p.
In our calculation, we have eliminated the second possibility beforehand, but that is not essential.
In the first case, the explicit powers of p cancel, and we are left with
choose(n,k) = a! / (b! * c!) * cop(a,A) / (cop(b,B) * cop(c,C))
= choose(a,b) * cop(a,A) / (cop(b,B) * cop(c,C))
Any powers of p dividing choose(n,k) come from choose(a,b) - in our case, there will be none, since we've eliminated these cases before - and, although cop(a,A) / (cop(b,B) * cop(c,C)) need not be an integer (consider e.g. choose(19,9) (mod 5)), when considering the expression modulo p, cop(m,r) reduces to (-1)^m * r!, so, since a = b + c, the (-1) cancel and we are left with
choose(n,k) ≡ choose(a,b) * choose(A,B) (mod p)
In the second case, we find
choose(n,k) = choose(a,b) * p * cop(a,A)/ (cop(b,B) * cop(c,C))
since a = b + c + 1. The carry in the last digit means that A < B, so modulo p
p * cop(a,A) / (cop(b,B) * cop(c,C)) ≡ 0 = choose(A,B)
(where we can either replace the division with a multiplication by the modular inverse, or view it as a congruence of rational numbers, meaning the numerator is divisible by p). Anyway, we again find
choose(n,k) ≡ choose(a,b) * choose(A,B) (mod p)
Now we can recur for the choose(a,b) part.
Example:
choose(144,6) (mod 5)
144 = 28 * 5 + 4
6 = 1 * 5 + 1
choose(144,6) ≡ choose(28,1) * choose(4,1) (mod 5)
≡ choose(3,1) * choose(4,1) (mod 5)
≡ 3 * 4 = 12 ≡ 2 (mod 5)
choose(12349,789) ≡ choose(2469,157) * choose(4,4)
≡ choose(493,31) * choose(4,2) * choose(4,4
≡ choose(98,6) * choose(3,1) * choose(4,2) * choose(4,4)
≡ choose(19,1) * choose(3,1) * choose(3,1) * choose(4,2) * choose(4,4)
≡ 4 * 3 * 3 * 1 * 1 = 36 ≡ 1 (mod 5)
Now the implementation:
// Preconditions: 0 <= k <= n; p > 1 prime
long long choose_mod_one(long long n, long long k, long long p)
{
// For small k, no recursion is necessary
if (k < p) return choose_mod_two(n,k,p);
long long q_n, r_n, q_k, r_k, choose;
q_n = n / p;
r_n = n % p;
q_k = k / p;
r_k = k % p;
choose = choose_mod_two(r_n, r_k, p);
// If the exponent of p in choose(n,k) isn't determined to be 0
// before the calculation gets serious, short-cut here:
/* if (choose == 0) return 0; */
choose *= choose_mod_one(q_n, q_k, p);
return choose % p;
}
// Preconditions: 0 <= k <= min(n,p-1); p > 1 prime
long long choose_mod_two(long long n, long long k, long long p)
{
// reduce n modulo p
n %= p;
// Trivial checks
if (n < k) return 0;
if (k == 0 || k == n) return 1;
// Now 0 < k < n, save a bit of work if k > n/2
if (k > n/2) k = n-k;
// calculate numerator and denominator modulo p
long long num = n, den = 1;
for(n = n-1; k > 1; --n, --k)
{
num = (num * n) % p;
den = (den * k) % p;
}
// Invert denominator modulo p
den = invert_mod(den,p);
return (num * den) % p;
}
To calculate the modular inverse, you can use Fermat's (so-called little) theorem
If p is prime and a not divisible by p, then a^(p-1) ≡ 1 (mod p).
and calculate the inverse as a^(p-2) (mod p), or use a method applicable to a wider range of arguments, the extended Euclidean algorithm or continued fraction expansion, which give you the modular inverse for any pair of coprime (positive) integers:
long long invert_mod(long long k, long long m)
{
if (m == 0) return (k == 1 || k == -1) ? k : 0;
if (m < 0) m = -m;
k %= m;
if (k < 0) k += m;
int neg = 1;
long long p1 = 1, p2 = 0, k1 = k, m1 = m, q, r, temp;
while(k1 > 0) {
q = m1 / k1;
r = m1 % k1;
temp = q*p1 + p2;
p2 = p1;
p1 = temp;
m1 = k1;
k1 = r;
neg = !neg;
}
return neg ? m - p2 : p2;
}
Like calculating a^(p-2) (mod p), this is an O(log p) algorithm, for some inputs it's significantly faster (it's actually O(min(log k, log p)), so for small k and large p, it's considerably faster), for others it's slower.
Overall, this way we need to calculate at most O(log_p k) binomial coefficients modulo p, where each binomial coefficient needs at most O(p) operations, yielding a total complexity of O(p*log_p k) operations.
When k is significantly larger than p, that is much better than the O(k) solution. For k <= p, it reduces to the O(k) solution with some overhead.
If you're calculating it more than once, there's another way that's faster. I'm going to post code in python because it'll probably be the easiest to convert into another language, although I'll put the C++ code at the end.
Calculating Once
Brute force:
def choose(n, k, m):
ans = 1
for i in range(k): ans *= (n-i)
for i in range(k): ans //= i
return ans % m
But the calculation can get into very big numbers, so we can use modular airthmetic tricks instead:
(a * b) mod m = (a mod m) * (b mod m) mod m
(a / (b*c)) mod m = (a mod m) / ((b mod m) * (c mod m) mod m)
(a / b) mod m = (a mod m) * (b mod m)^-1
Note the ^-1 at the end of the last equation. This is the multiplicative inverse of b mod m. It basically means that ((b mod m) * (b mod m)^-1) mod m = 1, just like how a * a^-1 = a * 1/a = 1 with (non-zero) integers.
This can be calculated in a few ways, one of which is the extended euclidean algorithm:
def multinv(n, m):
''' Multiplicative inverse of n mod m '''
if m == 1: return 0
m0, y, x = m, 0, 1
while n > 1:
y, x = x - n//m*y, y
m, n = n%m, m
return x+m0 if x < 0 else x
Note that another method, exponentiation, works only if m is prime. If it is, you can do this:
def powmod(b, e, m):
''' b^e mod m '''
# Note: If you use python, there's a built-in pow(b, e, m) that's probably faster
# But that's not in C++, so you can convert this instead:
P = 1
while e:
if e&1: P = P * b % m
e >>= 1; b = b * b % m
return P
def multinv(n, m):
''' Multiplicative inverse of n mod m, only if m is prime '''
return powmod(n, m-2, m)
But note that the Extended Euclidean Algorithm tends to still run faster, even though they technically have the same time complexity, O(log m), because it has a lower constant factor.
So now the full code:
def multinv(n, m):
''' Multiplicative inverse of n mod m in log(m) '''
if m == 1: return 0
m0, y, x = m, 0, 1
while n > 1:
y, x = x - n//m*y, y
m, n = n%m, m
return x+m0 if x < 0 else x
def choose(n, k, m):
num = den = 1
for i in range(k): num = num * (n-i) % m
for i in range(k): den = den * i % m
return num * multinv(den, m)
Querying Multiple Times
We can calculate the numerator and denominator separately, and then combine them. But notice that the product we're calculating for the numerator is n * (n-1) * (n-2) * (n-3) ... * (n-k+1). If you've ever learned about something called prefix sums, this is awfully similar. So let's apply it.
Precalculate fact[i] = i! mod m for i up to whatever the max value of n is, maybe 1e7 (ten million). Then, the numerator is (fact[n] * fact[n-k]^-1) mod m, and the denominator is fact[k]. So we can calculate choose(n, k, m) = fact[n] * multinv(fact[n-k], m) % m * multinv(fact[k], m) % m.
Python code:
MAXN = 1000 # Increase if necessary
MOD = 10**9+7 # A common mod that's used, change if necessary
fact = [1]
for i in range(1, MAXN+1):
fact.append(fact[-1] * i % MOD)
def multinv(n, m):
''' Multiplicative inverse of n mod m in log(m) '''
if m == 1: return 0
m0, y, x = m, 0, 1
while n > 1:
y, x = x - n//m*y, y
m, n = n%m, m
return x+m0 if x < 0 else x
def choose(n, k, m):
return fact[n] * multinv(fact[n-k] * fact[k] % m, m) % m
C++ code:
#include <iostream>
using namespace std;
const int MAXN = 1000; // Increase if necessary
const int MOD = 1e9+7; // A common mod that's used, change if necessary
int fact[MAXN+1];
int multinv(int n, int m) {
/* Multiplicative inverse of n mod m in log(m) */
if (m == 1) return 0;
int m0 = m, y = 0, x = 1, t;
while (n > 1) {
t = y;
y = x - n/m*y;
x = t;
t = m;
m = n%m;
n = t;
}
return x<0 ? x+m0 : x;
}
int choose(int n, int k, int m) {
return (long long) fact[n]
* multinv((long long) fact[n-k] * fact[k] % m, m) % m;
}
int main() {
fact[0] = 1;
for (int i = 1; i <= MAXN; i++) {
fact[i] = (long long) fact[i-1] * i % MOD;
}
cout << choose(4, 2, MOD) << '\n';
cout << choose(1e6, 1e3, MOD) << '\n';
}
Note that I'm casting to long long to avoid overflow.