I calculating ((A^B)/C)%M, but my code is not working when A,B,C,M are large in numbers. This code is giving right answer when A,B,C,D is small int.
What is wrong here?
Here C and M is co-prime
Sample input
2 3 4 5
Sample output
2
Code fails for these input
969109092 60139073 122541116 75884463
C program
#include <stdio.h>
int d,x,y;
Modular exponential (A^B)%M
int power(int A, int B, int M)
{
long long int result=1;
while(B>0)
{
if(B % 2 ==1)
{
result=(result * A)%M;
}
A=(A*A)%M;
B=B/2;
}
return result;
}
Modular multiplicative inverse
void extendedEuclid(int A, int B)
{
if(B == 0)
{
d = A;
x = 1;
y = 0;
}
else
{
extendedEuclid(B,A%B);
int temp = x;
x = y;
y = temp - (A/B)*y;
}
}
int modInv(int A, int M)
{
extendedEuclid(A,M);
return (x%M+M)%M;
}
main()
int main()
{
int A,B,C,M;
scanf("%d %d %d %d",&A,&B,&C,&M);
int inv = modInv(C,M)%M;
printf("%d\n",inv);
long long int p = (power(A,B,M))%M;
printf("%d\n",p);
long long int ans = (p * inv)%M;
//printf("%d",((modInv(C,M)*(power(A,B,M))))%M);
printf("%lld",ans);
return 0;
}
Code has at least the following issues:
int overflow in A*A. Code needs to calculate the product A*A using wider math. That is why code works with small values, but not large.
// A=(A*A)%M;
A = ((long long)A*A) % M;
// or
A = (1LL*A*A) % M;
Wrong print specifier. This implies compiler warnings are not fully enabled. Save time, Enable them all.
long long int p = (power(A,B,M))%M;
// printf("%d\n",p);
printf("%lld\n",p);
Code is amiss with negative values. Rather than patch that int hole, use unsigned types.
unsigned power(unsigned A, unsigned B, unsigned M) {
unsigned long long result = 1;
...
Failed corner case in power(A,0,1). result should be 0 when M==1.
// long long int result=1;
long long int result=1%M;
Test version with fixes noted in comments:
#include <stdio.h>
int d,x,y;
int power(int A, int B, int M)
{
long long int result=1;
long long int S = A; /* fix */
while(B>0)
{
if(B % 2 ==1)
{
result=(result * S)%M; /* fix */
}
S=(S*S)%M; /* fix */
B=B/2;
}
return (int)result;
}
void extendedEuclid(int A, int B)
{
int temp; /* C */
if(B == 0)
{
d = A;
x = 1;
y = 0;
}
else
{
extendedEuclid(B,A%B);
temp = x;
x = y;
y = temp - (A/B)*y;
}
}
int modInv(int A, int M)
{
extendedEuclid(A,M);
/* x = x%M; ** not needed */
if (x < 0) /* fix */
x += M; /* fix */
return (x); /* fix */
}
int main()
{
int A,B,C,M; /* C */
int inv, p, ans; /* C */
A = 969109092; /* 2^2 × 3^2 ×7 × 1249 × 3079 */
B = 60139073; /* 60139073 */
C = 122541116; /* 2^2 × 1621 × 18899 */
M = 75884463; /* 3^2 × 8431607 */
inv = modInv(C,M)%M; /* 15543920 */
printf("%d\n",inv);
p = power(A,B,M)%M; /* 6704397 */
printf("%d\n",p);
ans = (unsigned)(((unsigned long long)p * inv)%M); /* fix 22271562 */
printf("%d\n",ans);
return 0;
}
The value of int is probably not large enough, try with long, or double.
Be careful because power returns an int not long long int
You can try the mod_inv C function :
// return a modular multiplicative inverse of n with respect to the modulus.
// return 0 if the linear congruence has no solutions.
unsigned mod_inv(unsigned ra, unsigned rb) {
unsigned rc, sa = 1, sb = 0, sc, i = 0;
if (rb > 1) do {
rc = ra % rb;
sc = sa - (ra / rb) * sb;
sa = sb, sb = sc;
ra = rb, rb = rc;
} while (++i, rc);
sa *= (i *= ra == 1) != 0;
sa += (i & 1) * sb;
return sa;
}
This is basically the standard algorithm, to avoid overflows the signs are stored into the d variable, you could use a struct to do this. Also, when n = 1 and mod = 0 the output is 0, not 1, i think we have not many computations to execute modulo 0.
The modular multiplicative inverse of an integer N modulo m is an integer n such as the inverse of N modulo m equals n, if a modular inverse exists then it is unique. To calculate the value of the modulo inverse, use the extended euclidean algorithm which finds solutions to the Bezout identity.
Example of usage :
#include <assert.h>
int main(void) {
unsigned n, mod, res;
n = 52, mod = 107;
res = mod_inv(n, mod);
assert(res == 35); // 35 is a solution of the linear congruence.
n = 66, mod = 123;
res = mod_inv(n, mod);
assert(res == 0); // 66 does note have an inverse modulo 123.
}
/*
n = 7 and mod = 45 then res = 13 so 1 == ( 13 * 7 ) % 45
n = 52 and mod = 107 then res = 35 so 1 == ( 35 * 52 ) % 107
n = 213 and mod = 155 then res = 147 so 1 == ( 147 * 213 ) % 155
n = 392 and mod = 45 then res = 38 so 1 == ( 38 * 392 ) % 45
n = 687 and mod = 662 then res = 53 so 1 == ( 53 * 687 ) % 662
n = 451 and mod = 799 then res = 512 so 1 == ( 512 * 451 ) % 799
n = 1630 and mod = 259 then res = 167 so 1 == ( 167 * 1630 ) % 259
n = 4277 and mod = 4722 then res = 191 so 1 == ( 191 * 4277 ) % 4722
*/
Source
Related
I want to take modular inverse(k≥1) of integer and then multiply the result to another integer, as explain in following expression:
result=((x^(-k)))*y mod z
How can i implement this expression, where k≥1?
You need to define four function:
uint64_t modular_exponentiation(uint64_t x, uint64_t y, uint64_t z)
{
uint64_t res = 1;
x = x % z;
while (y > 0)
{
if (y & 1)
res = (res*x) % p;
y = y>>1; // y = y/2
x = (x*x) % z;
}
return res;
}
uint64_t moduloMultiplication(uint64_t a, uint64_t b,uint64_t z)
{
uint64_t res = 0;
a %= z;
while (b)
{
if (b & 1)
res = (res + a) % z;
a = (2 * a) % p;
b >>= 1; // b = b / 2
}
return res;
}
void extendedEuclid(uint64_t A, uint64_t B)
{
uint64_t temp;
if(B == 0)
{
d = A;
x = 1;
y = 0;
}
else
{
extendedEuclid(B,A%B);
temp = x;
x = y;
y = temp - (A/B)*y;
}
}
int modInverse(uint64_t A, uint64_t M)
{
extendedEuclid(A,M);
if (x < 0)
x += M;
return (x);
}
In main():
uint64_t result=0x00;
result=modular_exponentiation(x,k,z); // (x^k) mod z
result=modInverse(result,z); // ((x^k)^-1) mod z == x^(-k) mod z
result=moduloMultiplication(result,y,z);// x^(-k) * y mod z
You will need the extended greatest common divisor to compute the inverse of x for modulus z. When x and zare relatively prime you have a * x + b * z = 1 = gcd(x, z). And thus, a * x = 1 - b * z or a * x = 1 mod z, and a is the inverse to x in the modulus z.
Now you may compute result with x^-1 = a mod z:
result = power(a, k) * y % z
with ordinary integer arithmetic in C, where power() is the ordinary integer exponentiation.
Since the coefficients in such calculations can become very large very quickly, it is better to use ready-made libraries (e.g. gmp).
You can try the mod_inv C function :
// return a modular multiplicative inverse of n with respect to the modulus.
// return 0 if the linear congruence has no solutions.
unsigned mod_inv(unsigned ra, unsigned rb) {
unsigned rc, sa = 1, sb = 0, sc, i = 0;
if (rb > 1) do {
rc = ra % rb;
sc = sa - (ra / rb) * sb;
sa = sb, sb = sc;
ra = rb, rb = rc;
} while (++i, rc);
sa *= (i *= ra == 1) != 0;
sa += (i & 1) * sb;
return sa;
}
This is basically the standard algorithm, when n = 1 and mod = 0 the output is 0, not 1, i think we have not many computations to execute modulo 0.
The modular multiplicative inverse of an integer N modulo m is an integer n such as the inverse of N modulo m equals n, if a modular inverse exists then it is unique. To calculate the value of the modulo inverse, use the extended euclidean algorithm which finds solutions to the Bezout identity.
Example of usage :
#include <assert.h>
int main(void) {
unsigned n, mod, res;
n = 52, mod = 107;
res = mod_inv(n, mod);
assert(res == 35); // 35 is a solution of the linear congruence.
n = 66, mod = 123;
res = mod_inv(n, mod);
assert(res == 0); // 66 does note have an inverse modulo 123.
}
/*
n = 7 and mod = 45 then res = 13 so 1 == ( 13 * 7 ) % 45
n = 52 and mod = 107 then res = 35 so 1 == ( 35 * 52 ) % 107
n = 213 and mod = 155 then res = 147 so 1 == ( 147 * 213 ) % 155
n = 392 and mod = 45 then res = 38 so 1 == ( 38 * 392 ) % 45
n = 687 and mod = 662 then res = 53 so 1 == ( 53 * 687 ) % 662
n = 451 and mod = 799 then res = 512 so 1 == ( 512 * 451 ) % 799
n = 1630 and mod = 259 then res = 167 so 1 == ( 167 * 1630 ) % 259
n = 4277 and mod = 4722 then res = 191 so 1 == ( 191 * 4277 ) % 4722
*/
Source
Not really sure what the problem is here. I know I have the factorial function correct because I tested it separately. But the function that calculates e is tripping me up. All I have to do is add all the values after each factorial has been calculated. But I am having trouble translating that into C code. The problem for sure is in my second function. Any help or pointers would be appreciated.
#include <stdio.h>
#include <math.h>
#define NOERROR 0
#define DECIMAL_PLACES 16
#define EXPECTED_E 2.7182818284590452L
long calcFactorial(int);
double calcE(int);
long calcFactorial(int n)
{
long sum = 0;
sum = n;
if(n == 0)
{
return 1;
}
else
{
while(n != 1)
{
sum = sum * (n - 1);
n = n - 1;
}
printf("factorial sum: %ld\n", sum);
return sum;
}
}
double calcE(int n)
{
double e = 0;
int counter = 0;
for (counter = 0; counter < DECIMAL_PLACES; counter++)
{
e = e + (1/calcFactorial(n));
n--;
}
printf("Expected e value: %0.16Lf\n", EXPECTED_E);
printf("Calculated e value: %0.16d\n", e);
return e;
}
int main()
{
calcE(10);
}
You have a lot of errors in your code:
using long to store floating point result. Use double
passing n but looping using a bigger value: n becomes negative after a while: infinite loop
e = e + (1/calcFactorial(counter)); adds 0 to e most of the time because calcFactorial returns an integer (long)
EXPECTED_E constant had L suffix, which means long. Not what you want.
Fixed version:
#include <stdio.h>
#include <math.h>
#define NOERROR 0
#define DECIMAL_PLACES 16
#define EXPECTED_E 2.7182818284590452
long calcFactorial(int);
void calcE(int);
long calcFactorial(int n)
{
long sum = 0;
sum = n;
if(n == 0)
{
return 1;
}
else
{
while(n != 1)
{
sum *= (n - 1);
n = n - 1;
}
return sum;
}
}
void calcE(int n)
{
double e = 0;
int counter = 0;
for (counter = 0; counter < n; counter++)
{
e = e + (1.0/calcFactorial(counter));
}
printf("Expected e value: %0.16lf\n", EXPECTED_E);
printf("Calculated e value: %0.16lf\n", e);
}
int main( )
{
calcE(10);
}
This code outputs:
Expected e value: 2.7182818284590451
Calculated e value: 2.7182815255731922
Note: you are limited to a given maximum for n because after that you'll overflow long. Maybe consider using long long or unsigned long long for the factorial part (and even with that you're severely limited).
Jean-François Fabre highlighted your formal errors quite well, but it is not so far fetched to calculate with integers up to the final division--which must be done with floats, of course. The trick can be done with a method called binary splitting and, to my own surprise, it works very well native doubles, only one decimal digit off. It is also very simple to implement (code below written with legibility in mind).
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define BS_AFU 0
#define BS_AOK 1
static int exp1_bin_split(uint64_t a, uint64_t b, uint64_t *P, uint64_t *Q){
int err = BS_AOK;
uint64_t p1, q1, p2, q2, t1, one;
one = 1UL;
t1 = b - a;
if(t1 == one){
*P = one;
*Q = b;
return err;
}
t1 = (a + b) >> 1;
err = exp1_bin_split(a, t1, &p1, &q1);
if(err != BS_AOK){
return err;
}
err = exp1_bin_split(t1, b, &p2, &q2);
if(err != BS_AOK){
return err;
}
*P = q2 * p1 + p2;
*Q = q1 * q2;
return err;
}
#include <float.h>
static int exp1(double *a){
int err = BS_AOK;
uint64_t p = 0UL, q = 0UL, zero = 0UL;
double dp, dq;
// DBL_DIG + 2 = 17 here on my machine
// had DBL_DIG + 1 first but found out via T&E that
// one more is still inside the precision of a binary64
err = exp1_bin_split(zero, DBL_DIG + 2, &p, &q);
if(err != BS_AOK){
return err;
}
p = p + q;
dp = (double) p;
dq = (double) q;
*a = dp/dq;
return err;
}
int main(void){
double e = 0.0;
int err = BS_AOK;
err = exp1(&e);
if(err != BS_AOK){
fprintf(stderr,"Something went wrong in computing e\n");
exit(EXIT_FAILURE);
}
printf("exp(1) ~ 2.7182818284590452353602874713526624978\nexp1 ~ %.20g\n",e);
exit(EXIT_SUCCESS);
}
It uses the same algorithm as you do but does not compute the individual fractions and sums them up as floats but does it all at once with integers such that we have a large fraction at the end to resemble the approximation of exp(1). That explanation is a bit over-simplified, please read the linked paper for the details.
Let ib be the input base and ob the output base. str is the ASCII representation of some arbitrary large integer x. I need to define f such as:
f(str="1234567890", ib=10, ob=16) = {4, 9, 9, 6, 0, 2, 13, 2}
... where the return type of f is an int array containing the base ob digits of this integer. We assume that 2 >= ob <= MAX_INT and 2 >= ib <= 10, and str will always be a valid string (no negative needed).
Something to get OP started, but enough to leave OP to enjoy the coding experience.
// form (*d) = (*d)*a + b
static void mult_add(int *d, size_t *width, int ob, int a, int b) {
// set b as the carry
// for *width elements,
// x = (Multiply d[] by `a` (using wider than int math) and add carry)
// d[] = x mod ob
// carry = x/ob
// while (carry <> 0)
// widen d
// x = carry
// d[] = x mod ob
// carry = x/ob
}
int *ql_f(const char *src, int ib, int ob) {
// Validate input
assert(ib >= 2 && ib <= 10);
assert(ob >= 2 && ob <= INT_MAX);
assert(src);
// Allocate space
size_t length = strlen(src);
// + 2 + 4 is overkill, OP to validate and right-size later
size_t dsize = (size_t) (log(ib)/log(ob)*length + 2 + 4);
int *d = malloc(sizeof *d * dsize);
assert(d);
// Initialize d to zero
d[0] = 0;
size_t width = 1;
while (*src) {
mult_add(d, &width, ob, ib, *src - '0');
src++;
}
// add -1 to end, TBD code
return d;
}
I wrote this with older specifications, so it's not valid any more, but it might be useful as a starting point.
The code can handle long long magnitudes. Going to arbitrary precision numbers in C is a big leap!
Note using -1 as the ending marker instead of 0. Can accept ib from 2 to 36 and any ob.
Includes example main.
Function f is not reentrant as-is. To make it thread-safe, it could allocate the required memory then return a pointer to it. The simplest protocol would be having the caller responsible for freeing the memory afterwards.
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
int *f(const char *str, int ib, int ob) {
static int result[CHAR_BIT * sizeof(long long) + 1];
int i = sizeof(result) / sizeof(int) - 1;
long long l = strtoll(str, NULL, ib);
result[i--] = -1;
while (l) {
result[i] = l % ob;
l /= ob;
i--;
}
return result + i + 1;
}
int main()
{
int *x = f("1234567890", 16, 10);
while (*x > -1) {
printf("%d ", *x);
x++;
}
return 0;
}
For solving project euler problem 20 to find the sum of digits in 100! i am running the following program , it is working for factorial of small numbers but not for 100.which data type should i use or is it necessary to use an array for storing the digits?
int rec(int);
void main()
{
int f=1,i=1,z,s=0,r,n;
while(i<=100)
{
f=f*i;
f=rec(f);
i++;
}
n=f;
while(n!=0)
{
r=n%10;
n=n/10;
s=s+r;
}
printf("\n%d",s);
}
int rec(int t)
{
if(t%10==0)
{
t=t/10;
rec(t);
}
return t;
}
Approximate factorial of 100 can be calculated using the double type. You can also use the Stirling's formula, stating that
n! ≈ sqrt(2*M_PI*n) * pow(n/exp(0),n)
If you plug in the numbers, you'll get n! ≈ 9*10157. That means your type needs to be able to hold 158 decimal digits or, equivalently, ~log2(9*10157) = 525 bits or 66 8-bit bytes.
No fundamental numeric type in C is big enough. The largest you are guaranteed to get is 64 bits (if you use unsigned long long).
So, if you want to calculate n! in C, you either need to construct long arithmetic multiplication by hand or use a special library that can do that for you.
For this relatively simple task you can actually implement long multiplication and use it to get the factorial value by repeated multiplication.
In the following program I've used an in-place multiplication algorithm, which modifies one of the multiplicands in the process and eventually replaces it with the product. The algorithm can be derived directly from the long multiplication known from school.
This program calculates factorials of integers from 1 up to and including 100:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
typedef unsigned char uint8;
typedef unsigned short uint16;
#if UINT_MAX >= 0xFFFFFFFF
typedef unsigned uint32;
#else
typedef unsigned long uint32;
#endif
typedef unsigned uint;
void MulInPlace(uint8* dst/* n bytes */,
const uint8* src/* n bytes */,
uint n)
{
uint c1, c2;
if (n >= 0xFFFF) abort();
for (c1 = n - 1; c1 != ~0u; c1--)
{
uint16 s = 0;
uint32 p = 0; // p must be able to store ceil(log2(n))+2*8 bits
for (c2 = c1; c2 != ~0u; c2--)
{
p += dst[c2] * src[c1 - c2];
}
dst[c1] = (uint8)(p & 0xFF);
for (c2 = c1 + 1; c2 < n; c2++)
{
p >>= 8;
s += dst[c2] + (uint8)(p & 0xFF);
dst[c2] = (uint8)(s & 0xFF);
s >>= 8;
}
}
}
int ByteDivInPlace(uint8* dst/* n bytes */,
uint n,
uint8 divisor,
uint8* remainder)
{
uint rem = 0;
int nonzero = 0;
while (n)
{
rem += dst[n - 1];
nonzero |= (dst[n - 1] = rem / divisor);
rem = (rem % divisor) << 8;
n--;
}
if (remainder != NULL)
*remainder = (uint8)(rem >> 8);
return nonzero; // 1 if the quotient is non-zero, 0 otherwise
}
void IncInPlace(uint8* dst/* n bytes */,
uint n)
{
uint c = 1;
while (n-- && c)
{
c += *dst;
*dst++ = c & 0xFF;
c >>= 8;
}
}
void DestroyingDecimalPrint(uint8* dst, uint n)
{
uint8 r;
if (ByteDivInPlace(dst, n, 10, &r))
DestroyingDecimalPrint(dst, n);
printf("%d", r);
}
int main(void)
{
int i;
uint8 factorial[66];
uint8 factor[sizeof(factorial)];
uint8 tmp[sizeof(factorial)];
// factor = 1
memset(factor, 0, sizeof(factor));
factor[0] = 1;
// factorial = 1
memcpy(factorial, factor, sizeof(factorial));
for (i = 1; i <= 100; i++)
{
// factorial *= factor
MulInPlace(factorial, factor, sizeof(factorial));
// tmp = factorial
memcpy(tmp, factorial, sizeof(factorial));
// print i and tmp
printf("%i! = ", i);
DestroyingDecimalPrint(tmp, sizeof(tmp));
printf("\n");
// factor += 1
IncInPlace(factor, sizeof(factor));
}
return 0;
}
Output (ideone):
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600
13! = 6227020800
14! = 87178291200
15! = 1307674368000
16! = 20922789888000
17! = 355687428096000
18! = 6402373705728000
19! = 121645100408832000
20! = 2432902008176640000
21! = 51090942171709440000
22! = 1124000727777607680000
23! = 25852016738884976640000
24! = 620448401733239439360000
25! = 15511210043330985984000000
26! = 403291461126605635584000000
27! = 10888869450418352160768000000
28! = 304888344611713860501504000000
29! = 8841761993739701954543616000000
30! = 265252859812191058636308480000000
31! = 8222838654177922817725562880000000
32! = 263130836933693530167218012160000000
33! = 8683317618811886495518194401280000000
34! = 295232799039604140847618609643520000000
35! = 10333147966386144929666651337523200000000
36! = 371993326789901217467999448150835200000000
37! = 13763753091226345046315979581580902400000000
38! = 523022617466601111760007224100074291200000000
39! = 20397882081197443358640281739902897356800000000
40! = 815915283247897734345611269596115894272000000000
41! = 33452526613163807108170062053440751665152000000000
42! = 1405006117752879898543142606244511569936384000000000
43! = 60415263063373835637355132068513997507264512000000000
44! = 2658271574788448768043625811014615890319638528000000000
45! = 119622220865480194561963161495657715064383733760000000000
46! = 5502622159812088949850305428800254892961651752960000000000
47! = 258623241511168180642964355153611979969197632389120000000000
48! = 12413915592536072670862289047373375038521486354677760000000000
49! = 608281864034267560872252163321295376887552831379210240000000000
50! = 30414093201713378043612608166064768844377641568960512000000000000
51! = 1551118753287382280224243016469303211063259720016986112000000000000
52! = 80658175170943878571660636856403766975289505440883277824000000000000
53! = 4274883284060025564298013753389399649690343788366813724672000000000000
54! = 230843697339241380472092742683027581083278564571807941132288000000000000
55! = 12696403353658275925965100847566516959580321051449436762275840000000000000
56! = 710998587804863451854045647463724949736497978881168458687447040000000000000
57! = 40526919504877216755680601905432322134980384796226602145184481280000000000000
58! = 2350561331282878571829474910515074683828862318181142924420699914240000000000000
59! = 138683118545689835737939019720389406345902876772687432540821294940160000000000000
60! = 8320987112741390144276341183223364380754172606361245952449277696409600000000000000
61! = 507580213877224798800856812176625227226004528988036003099405939480985600000000000000
62! = 31469973260387937525653122354950764088012280797258232192163168247821107200000000000000
63! = 1982608315404440064116146708361898137544773690227268628106279599612729753600000000000000
64! = 126886932185884164103433389335161480802865516174545192198801894375214704230400000000000000
65! = 8247650592082470666723170306785496252186258551345437492922123134388955774976000000000000000
66! = 544344939077443064003729240247842752644293064388798874532860126869671081148416000000000000000
67! = 36471110918188685288249859096605464427167635314049524593701628500267962436943872000000000000000
68! = 2480035542436830599600990418569171581047399201355367672371710738018221445712183296000000000000000
69! = 171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000
70! = 11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000
71! = 850478588567862317521167644239926010288584608120796235886430763388588680378079017697280000000000000000
72! = 61234458376886086861524070385274672740778091784697328983823014963978384987221689274204160000000000000000
73! = 4470115461512684340891257138125051110076800700282905015819080092370422104067183317016903680000000000000000
74! = 330788544151938641225953028221253782145683251820934971170611926835411235700971565459250872320000000000000000
75! = 24809140811395398091946477116594033660926243886570122837795894512655842677572867409443815424000000000000000000
76! = 1885494701666050254987932260861146558230394535379329335672487982961844043495537923117729972224000000000000000000
77! = 145183092028285869634070784086308284983740379224208358846781574688061991349156420080065207861248000000000000000000
78! = 11324281178206297831457521158732046228731749579488251990048962825668835325234200766245086213177344000000000000000000
79! = 894618213078297528685144171539831652069808216779571907213868063227837990693501860533361810841010176000000000000000000
80! = 71569457046263802294811533723186532165584657342365752577109445058227039255480148842668944867280814080000000000000000000
81! = 5797126020747367985879734231578109105412357244731625958745865049716390179693892056256184534249745940480000000000000000000
82! = 475364333701284174842138206989404946643813294067993328617160934076743994734899148613007131808479167119360000000000000000000
83! = 39455239697206586511897471180120610571436503407643446275224357528369751562996629334879591940103770870906880000000000000000000
84! = 3314240134565353266999387579130131288000666286242049487118846032383059131291716864129885722968716753156177920000000000000000000
85! = 281710411438055027694947944226061159480056634330574206405101912752560026159795933451040286452340924018275123200000000000000000000
86! = 24227095383672732381765523203441259715284870552429381750838764496720162249742450276789464634901319465571660595200000000000000000000
87! = 2107757298379527717213600518699389595229783738061356212322972511214654115727593174080683423236414793504734471782400000000000000000000
88! = 185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000
89! = 16507955160908461081216919262453619309839666236496541854913520707833171034378509739399912570787600662729080382999756800000000000000000000
90! = 1485715964481761497309522733620825737885569961284688766942216863704985393094065876545992131370884059645617234469978112000000000000000000000
91! = 135200152767840296255166568759495142147586866476906677791741734597153670771559994765685283954750449427751168336768008192000000000000000000000
92! = 12438414054641307255475324325873553077577991715875414356840239582938137710983519518443046123837041347353107486982656753664000000000000000000000
93! = 1156772507081641574759205162306240436214753229576413535186142281213246807121467315215203289516844845303838996289387078090752000000000000000000000
94! = 108736615665674308027365285256786601004186803580182872307497374434045199869417927630229109214583415458560865651202385340530688000000000000000000000
95! = 10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000
96! = 991677934870949689209571401541893801158183648651267795444376054838492222809091499987689476037000748982075094738965754305639874560000000000000000000000
97! = 96192759682482119853328425949563698712343813919172976158104477319333745612481875498805879175589072651261284189679678167647067832320000000000000000000000
98! = 9426890448883247745626185743057242473809693764078951663494238777294707070023223798882976159207729119823605850588608460429412647567360000000000000000000000
99! = 933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000
100! = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
You should look for overflow, print the value after each iteration.
Note that rec(t); doesn't do anything as it doesn't use the returned value... you want t = rec(t);.
int is definitely too short, try long long... if that's still overflowing, you need another data structure.. eg: GMP Library.
Note: using some "proper" language for the job might give you some insight to the range you have to support... e.g. with python:
>>> import math
>>> math.factorial(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000L
private static void problem20()
{
string muliplent = "100";
for (int i = 99; i > 1; i--)
{
muliplent = getproduct(muliplent, i);
}
int sum = 0;
char[] result=muliplent.ToCharArray();
int count = muliplent.ToCharArray().Count();
for (int j = 0; j < count; j++)
{
sum = sum + (result[j] - '0');
}
Console.WriteLine("sum is {0}", sum);
Console.ReadLine();
}
private static string getproduct(string multiplent, int multiplier)
{
StringBuilder str = new StringBuilder();
int product = 0;
int remainder = 0;
int dividend = 0;
char[] c = multiplent.ToCharArray();
for (int i = c.Count() - 1; i >= 0; i--)
{
product = (((c[i] - '0') * multiplier) + dividend);
remainder = product % 10;
dividend = product / 10;
if (i != 0)
{
str.Insert(0, remainder);
}
}
str.Insert(0, product);
return str.ToString();
}
Can anyone help me out with the pollard rho implementation? I have implemented this in C. It's working fine for numbers upto 10 digits but it's not able to handle greater numbers.
Please help me out to improve it to carry out factorization of numbers upto 18 digits . My code is this:
#include<stdio.h>
#include<math.h>
int gcd(int a, int b)
{
if(b==0) return a ;
else
return(gcd(b,a%b)) ;
}
long long int mod(long long int a , long long int b , long long int n )
{
long long int x=1 , y=a ;
while(b>0)
{
if(b%2==1) x = ((x%n)*(y%n))%n ;
y = ((y%n)*(y%n))%n ;
b/=2 ;
}
return x%n ;
}
int isprimes(long long int u)
{
if(u==3)
return 1 ;
int a = 2 , i ;
long long int k , t = 0 , r , p ;
k = u-1 ;
while(k%2==0)
{ k/=2 ; t++ ; }
while(a<=3) /*der are no strong pseudoprimes common in base 2 and base 3*/
{
r = mod(a,k,u) ;
for(i = 1 ; i<=t ; i++)
{
p = ((r%u)*(r%u))%u ;
if((p==1)&&(r!=1)&&(r!=(u-1)))
{ return 0 ; }
r = p ;
}
if(p!=1)
return 0 ;
else
a++ ;
}
if(a==4)
return 1 ;
}
long long int pol(long long int u)
{
long long int x = 2 , k , i , a , y , c , s;
int d = 1 ;
k = 2 ;
i = 1 ;
y = x ;
a = u ;
if(isprimes(u)==1)
{
return 1;
}
c=-1 ;
s = 2 ;
while(1)
{
i++;
x=((x%u)*(x%u)-1)% u ;
d = gcd(abs(y-x),u) ;
if(d!=1&&d!=u)
{ printf("%d ",d);
while(a%d==0) { a=a/d; }
x = 2 ;
k = 2 ;
i = 1 ;
y = x ;
if(a==1)
{ return 0 ; }
if(isprimes(a)!=0)
{ return a ; }
u=a ;
}
if(i==k)
{y = x ; k*=2 ; c = x ;} /*floyd cycle detection*/
if(c==x)
{ x = ++s ; }
}
return ;
}
int main()
{
long long int t ;
long long int i , n , j , k , a , b , u ;
while(scanf("%lld",&n)&&n!=0)
{ u = n ; k = 0 ;
while(u%2==0)
{ u/=2 ; k = 1 ; }
if(k==1) printf("2 ") ;
if(u!=1)
t = pol(u) ;
if(u!=1)
{
if(t==1)
{ printf("%lld",u) ; }
else
if(t!=0)
{ printf("%lld",t) ; }
}
printf("\n");
}
return 0;
}
sorry for the long code ..... I am a new coder.
When you're multiplying two numbers modulo m, the intermediate product can become nearly m^2. So if you use a 64-bit unsigned integer type, the maximal modulus it can handle is 2^32, if the modulus is larger, overflow may happen. It will be rare when the modulus is only slightly larger, but that makes it only less obvious, you cannot rely on being lucky if the modulus allows the possibility of overflow.
You can gain a larger range by a factor of two if you choose a representative of the residue class modulo m of absolute value at most m/2 or something equivalent:
uint64_t mod_mul(uint64_t x, uint64_t y, uint64_t m)
{
int neg = 0;
// if x is too large, choose m-x and note that we need one negation for that at the end
if (x > m/2) {
x = m - x;
neg = !neg;
}
// if y is too large, choose m-y and note that we need one negation for that at the end
if (y > m/2) {
y = m - y;
neg = !neg;
}
uint64_t prod = (x * y) % m;
// if we had negated _one_ factor, and the product isn't 0 (mod m), negate
if (neg && prod) {
prod = m - prod;
}
return prod;
}
So that would allow moduli of up to 2^33 with a 64-bit unsigned type. Not a big step.
The recommended solution to the problem is the use of a big-integer library, for example GMP is available as a distribution package on most if not all Linux distros, and also (relatively) easily installable on Windows.
If that is not an option (really, are you sure?), you can get it to work for larger moduli (up to 2^63 for an unsigned 64-bit integer type) using Russian peasant multiplication:
x * y = 2 * (x * (y/2)) + (x * (y % 2))
so for the calculation, you only need that 2*(m-1) doesn't overflow.
uint64_t mod_mult(uint64_t x, uint64_t y, uint64_t m)
{
if (y == 0) return 0;
if (y == 1) return x % m;
uint64_t temp = mod_mult(x,y/2,m);
temp = (2*temp) % m;
if (y % 2 == 1) {
temp = (temp + x) % m;
}
return temp;
}
Note however that this algorithm needs O(log y) steps, so it's rather slow in practice. For smaller m you can speed it up, if 2^k*(m-1) doesn't overflow, you can proceed in steps of k bits instead of single bits (x*y = ((x * (y >> k)) << k) + (x * (y & ((1 << k)-1)))), which is a good improvement if your moduli are never larger than 48 or 56 bits, say.
Using that variant of modular multiplication, your algorithm will work for larger numbers (but it will be significantly slower). You can also try test for the size of the modulus and/or the factors to determine which method to use, if m < 2^32 or x < (2^64-1)/y, the simple (x * y) % m will do.
You can try this C implementation of Pollard Rho :
unsigned long long pollard_rho(const unsigned long long N) {
// Require : a composite number N, not a square.
// Ensure : res is a non-trivial factor of N.
// Option : define a timeout, define a rand function.
static const int timeout = 18;
static unsigned long long rand_val = 2994439072U;
rand_val = (rand_val * 1025416097U + 286824428U) % 4294967291LLU;
unsigned long long res = 1, a, b, c, i = 0, j = 1, x = 1, y = 1 + rand_val % (N - 1);
for (; res == 1; ++i) {
if (i == j) {
if (j >> timeout)
break;
j <<= 1;
x = y;
}
a = y, b = y;
for (y = 0; a; a & 1 ? b >= N - y ? y -= N : 0, y += b : 0, a >>= 1, (c = b) >= N - b ? c -= N : 0, b += c);
y = (1 + y) % N;
for (a = N, b = y > x ? y - x : x - y; (a %= b) && (b %= a););
res = a | b;
}
return res;
}
Otherwise there is a pure C quadratic sieve which factors numbers from 0 to 300-bit.