Hope you can help me; I have the following code:
#include <iostream>
#include <math.h>
using namespace std;
long int
cifra (long int b, long int e, long int n)
{
/* Calcula a tal que (b^e)=a MOD n. Algoritmo 3.1 de Allenby & Redfern,1989. */
long int a, i, q, r;
a = 1;
q = b / n;
r = b - q * n;
for (i = 1; i <= e; i++)
{
a = a * r;
q = a / n;
a = a - q * n; /* ou, de forma equivalente, a=mod(a,n) */
}
return a;
}
int
main ()
{
long int a, b, e, n;
b = 116104101;
e = 19661;
n = 383768051;
a = cifra (b, e, n);
cout << "a=" << a << endl;
return 0;
}
and this should output
a=199324862
as it does when I used the online C++ Compiler (https://www.onlinegdb.com/online_c++_compiler, which uses g++).
However: if I run it on Code::Blocks with MinGW64 (on Windows 10), I get the wrong result:
a=298405922
Any ideas? Am I doing anything wrong?
Overflow
q * n, a * r, q * n risk overflow.
The width of long is at least 32-bit, yet a full range multiplication obliges 2x long width for the product. On some platforms it is 64-bit and thus success with the test values on some, failure on others.
Either:
Use a wider type for intermediate calculations. long long would suffice for OP's test case of b = 116104101; e = 19661; n = 383768051; yet still fail with long long for b = 116104101<<32; e = 19661<<32; n = 383768051<<32;
or
Perform the math more carefully. Example: Modular exponentiation without range restriction.
Slow
for (i = 1; i <= e; i++) is very slow with large e. Research Modular exponentiation.
Bug
int64_t cifra(int64_t b, int64_t e, int64_t n) incorrect with some small corner cases. cifra(b, 0, 1) returns 1 when it should return 0.
// a = 1;
a = n > 1 ? 1 : 0;
// or
a = 1%n;
// or ...
Sample fix
Example fix for OP's code with limited range. I went for unsigned types as analyzing signed types with negative values is too tedious right now.
uint32_t cifra32(uint32_t b, uint32_t e, uint32_t n) {
uint64_t a = 1%n;
uint64_t q = b / n;
uint64_t r = b - q * n;
for (uint32_t i = 1; i <= e; i++) {
a = a * r;
q = a / n;
a = a - q * n;
}
return a;
}
More improvements possible.
It seems that you're assuming that long int is a 64-bit (or larger) integer type, but it's actually a 32-bit type in that particular environment. If you need a certain size type you should use something more explicit like int64_t or uint64_t. Also, you might want to use the remainder operator % to avoid the q variable altogether, e.g. r = b % n or just b %= n:
#include <iostream>
#include <cstdint>
int64_t cifra(int64_t b, int64_t e, int64_t n) {
/* Calcula a tal que (b^e)=a MOD n. Algoritmo 3.1 de Allenby & Redfern,1989. */
int64_t a, i;
a = 1;
b %= n;
for (i = 1; i <= e; i++) {
a = (a * b) % n; /* ou, de forma equivalente, a=mod(a,n) */
}
return a;
}
int main() {
int64_t a, b, e, n;
b = 116104101;
e = 19661;
n = 383768051;
a = cifra(b, e, n);
std::cout << "a=" << a << std::endl;
return 0;
}
Related
Given 3 numbers a b c get a^b , b^a , c^x where x is abs diff between b and a cout each one but mod 10^9+7 in ascending order.
well I searched web for how to use the distributive property but didn't understand it since I am beginner,
I use very simple for loops so understanding this problem is a bit hard for me so how can I relate these mod rules with powers too in loops? If anyone can help me I would be so happy.
note time limit is 1 second which makes it harder
I tried to mod the result every time in the loop then times it by the original number.
for example if 2^3 then 1st loop given variables cin>>a,a would be 2, num =a would be like this
a = (a % 10^9 + 7) * num this works for very small inputs but large ones it exceed time
#include <iostream>
#include <cmath>
using namespace std;
int main ()
{
long long a,b,c,one,two,thr;
long long x;
long long mod = 1e9+7;
cin>>a>>b>>c;
one = a;
two = b;
thr = c;
if (a>=b)
x = a - b;
else
x = b - a;
for(int i = 0; i < b-1;i++)
{
a = ((a % mod) * (one%mod))%mod;
}
for(int j = 0; j < a-1;j++)
{
b = ((b % mod) * (two%mod))%mod;
}
for(int k = 0; k < x-1;k++)
{
c = ((c % mod) * (thr%mod))%mod;
}
}
I use very simple for loops [...] this works for very small inputs, but large ones it exceeds time.
There is an algorithm called "exponentiation by squaring" that has a logarithmic time complexity, rather then a linear one.
It works breaking down the power exponent while increasing the base.
Consider, e.g. x355. Instead of multiplying x 354 times, we can observe that
x355 = x·x354 = x·(x2)177 = x·x2·(x2)176 = x·x2·(x4)88 = x·x2·(x8)44 = x·x2·(x16)22 = x·x2·(x32)11 = x·x2·x32·(x32)10 = x·x2·x32·(x64)5 = x·x2·x32·x64·(x64)4 = x·x2·x32·x64·(x128)2 = x1·x2·x32·x64·x256
That took "only" 12 steps.
To implement it, we only need to be able to perform modular multiplications safely, without overflowing. Given the value of the modulus, a type like std::int64_t is wide enough.
#include <iostream>
#include <cstdint>
#include <limits>
#include <cassert>
namespace modular
{
auto exponentiation(std::int64_t base, std::int64_t exponent) -> std::int64_t;
}
int main()
{
std::int64_t a, b, c;
std::cin >> a >> b >> c;
auto const x{ b < a ? a - b : b - a };
std::cout << modular::exponentiation(a, b) << '\n'
<< modular::exponentiation(b, a) << '\n'
<< modular::exponentiation(c, x) << '\n';
return 0;
}
namespace modular
{
constexpr std::int64_t M{ 1'000'000'007 };
// We need the mathematical modulo
auto from(std::int64_t x)
{
static_assert(M > 0);
x %= M;
return x < 0 ? x + M : x;
}
// It assumes that both a and b are already mod M
auto multiplication_(std::int64_t a, std::int64_t b)
{
assert( 0 <= a and a < M and 0 <= b and b < M );
assert( b == 0 or a <= std::numeric_limits<int64_t>::max() / b );
return (a * b) % M;
}
// Implements exponentiation by squaring
auto exponentiation(std::int64_t base, std::int64_t exponent) -> std::int64_t
{
assert( exponent >= 0 );
auto b{ from(base) };
std::int64_t x{ 1 };
while ( exponent > 1 )
{
if ( exponent % 2 != 0 )
{
x = multiplication_(x, b);
--exponent;
}
b = multiplication_(b, b);
exponent /= 2;
}
return multiplication_(b, x);
}
}
This problem's answer turns out to be calculating large binomial coefficients modulo prime number using Lucas' theorem. Here's the solution to that problem using this technique: here.
Now my questions are:
Seems like my code expires if the data increases due to overflow of variables. Any ways to handle this?
Are there any ways to do this without using this theorem?
EDIT: note that as this is an OI or ACM problem, external libs other than original ones are not permitted.
Code below:
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std;
#define N 100010
long long mod_pow(int a,int n,int p)
{
long long ret=1;
long long A=a;
while(n)
{
if (n & 1)
ret=(ret*A)%p;
A=(A*A)%p;
n>>=1;
}
return ret;
}
long long factorial[N];
void init(long long p)
{
factorial[0] = 1;
for(int i = 1;i <= p;i++)
factorial[i] = factorial[i-1]*i%p;
//for(int i = 0;i < p;i++)
//ni[i] = mod_pow(factorial[i],p-2,p);
}
long long Lucas(long long a,long long k,long long p)
{
long long re = 1;
while(a && k)
{
long long aa = a%p;long long bb = k%p;
if(aa < bb) return 0;
re = re*factorial[aa]*mod_pow(factorial[bb]*factorial[aa-bb]%p,p-2,p)%p;
a /= p;
k /= p;
}
return re;
}
int main()
{
int t;
cin >> t;
while(t--)
{
long long n,m,p;
cin >> n >> m >> p;
init(p);
cout << Lucas(n+m,m,p) << "\n";
}
return 0;
}
This solution assumes that p2 fits into an unsigned long long. Since an unsigned long long has at least 64 bits as per standard, this works at least for p up to 4 billion, much more than the question specifies.
typedef unsigned long long num;
/* x such that a*x = 1 mod p */
num modinv(num a, num p)
{
/* implement this one on your own */
/* you can use the extended Euclidean algorithm */
}
/* n chose m mod p */
/* computed with the theorem of Lucas */
num modbinom(num n, num m, num p)
{
num i, result, divisor, n_, m_;
if (m == 0)
return 1;
/* check for the likely case that the result is zero */
if (n < m)
return 0;
for (n_ = n, m_ = m; m_ > 0; n_ /= p, m_ /= p)
if (n_ % p < m_ % p)
return 0;
for (result = 1; n >= p || m >= p; n /= p, m /= p) {
result *= modbinom(n % p, m % p, p);
result %= p;
}
/* avoid unnecessary computations */
if (m > n - m)
m = n - m;
divisor = 1;
for (i = 0; i < m; i++) {
result *= n - i;
result %= p;
divisor *= i + 1;
divisor %= p;
}
result *= modinv(divisor, p);
result %= p;
return result;
}
An infinite precision integer seems like the way to go.
If you are in C++,
the PicklingTools library has an "infinite precision" integer (similar to
Python's LONG type). Someone else suggested Python, that's a reasonable
answer if you know Python. if you want to do it in C++, you can
use the int_n type:
#include "ocval.h"
int_n n="012345678910227836478627843";
n = n + 1; // Can combine with other plain ints as well
Take a look at the documentation at:
http://www.picklingtools.com/html/usersguide.html#c-int-n-and-the-python-arbitrary-size-ints-long
and
http://www.picklingtools.com/html/faq.html#c-and-otab-tup-int-un-int-n-new-in-picklingtools-1-2-0
The download for the C++ PicklingTools is here.
You want a bignum (a.k.a. arbitrary precision arithmetic) library.
First, don't write your own bignum (or bigint) library, because efficient algorithms (more efficient than the naive ones you learned at school) are difficult to design and implement.
Then, I would recommend GMPlib. It is free software, well documented, often used, quite efficient, and well designed (with perhaps some imperfections, in particular the inability to plugin your own memory allocator in replacement of the system malloc; but you probably don't care, unless you want to catch the rare out-of-memory condition ...). It has an easy C++ interface. It is packaged in most Linux distributions.
If it is a homework assignment, perhaps your teacher is expecting you to think more on the math, and find, with some proof, a way of solving the problem without any bignums.
Lets suppose that we need to compute a value of (a / b) mod p where p is a prime number. Since p is prime then every number b has an inverse mod p. So (a / b) mod p = (a mod p) * (b mod p)^-1. We can use euclidean algorithm to compute the inverse.
To get (n over k) we need to compute n! mod p, (k!)^-1, ((n - k)!)^-1. Total time complexity is O(n).
UPDATE: Here is the code in c++. I didn't test it extensively though.
int64_t fastPow(int64_t a, int64_t exp, int64_t mod)
{
int64_t res = 1;
while (exp)
{
if (exp % 2 == 1)
{
res *= a;
res %= mod;
}
a *= a;
a %= mod;
exp >>= 1;
}
return res;
}
// This inverse works only for primes p, it uses Fermat's little theorem
int64_t inverse(int64_t a, int64_t p)
{
assert(p >= 2);
return fastPow(a, p - 2, p);
}
int64_t binomial(int64_t n, int64_t k, int64_t p)
{
std::vector<int64_t> fact(n + 1);
fact[0] = 1;
for (auto i = 1; i <= n; ++i)
fact[i] = (fact[i - 1] * i) % p;
return ((((fact[n] * inverse(fact[k], p)) % p) * inverse(fact[n - k], p)) % p);
}
I want to find (n choose r) for large integers, and I also have to find out the mod of that number.
long long int choose(int a,int b)
{
if (b > a)
return (-1);
if(b==0 || a==1 || b==a)
return(1);
else
{
long long int r = ((choose(a-1,b))%10000007+(choose(a-1,b- 1))%10000007)%10000007;
return r;
}
}
I am using this piece of code, but I am getting TLE. If there is some other method to do that please tell me.
I don't have the reputation to comment yet, but I wanted to point out that the answer by rock321987 works pretty well:
It is fast and correct up to and including C(62, 31)
but cannot handle all inputs that have an output that fits in a uint64_t. As proof, try:
C(67, 33) = 14,226,520,737,620,288,370 (verify correctness and size)
Unfortunately, the other implementation spits out 8,829,174,638,479,413 which is incorrect. There are other ways to calculate nCr which won't break like this, however the real problem here is that there is no attempt to take advantage of the modulus.
Notice that p = 10000007 is prime, which allows us to leverage the fact that all integers have an inverse mod p, and that inverse is unique. Furthermore, we can find that inverse quite quickly. Another question has an answer on how to do that here, which I've replicated below.
This is handy since:
x/y mod p == x*(y inverse) mod p; and
xy mod p == (x mod p)(y mod p)
Modifying the other code a bit, and generalizing the problem we have the following:
#include <iostream>
#include <assert.h>
// p MUST be prime and less than 2^63
uint64_t inverseModp(uint64_t a, uint64_t p) {
assert(p < (1ull << 63));
assert(a < p);
assert(a != 0);
uint64_t ex = p-2, result = 1;
while (ex > 0) {
if (ex % 2 == 1) {
result = (result*a) % p;
}
a = (a*a) % p;
ex /= 2;
}
return result;
}
// p MUST be prime
uint32_t nCrModp(uint32_t n, uint32_t r, uint32_t p)
{
assert(r <= n);
if (r > n-r) r = n-r;
if (r == 0) return 1;
if(n/p - (n-r)/p > r/p) return 0;
uint64_t result = 1; //intermediary results may overflow 32 bits
for (uint32_t i = n, x = 1; i > r; --i, ++x) {
if( i % p != 0) {
result *= i % p;
result %= p;
}
if( x % p != 0) {
result *= inverseModp(x % p, p);
result %= p;
}
}
return result;
}
int main() {
uint32_t smallPrime = 17;
uint32_t medNum = 3001;
uint32_t halfMedNum = medNum >> 1;
std::cout << nCrModp(medNum, halfMedNum, smallPrime) << std::endl;
uint32_t bigPrime = 4294967291ul; // 2^32-5 is largest prime < 2^32
uint32_t bigNum = 1ul << 24;
uint32_t halfBigNum = bigNum >> 1;
std::cout << nCrModp(bigNum, halfBigNum, bigPrime) << std::endl;
}
Which should produce results for any set of 32-bit inputs if you are willing to wait. To prove a point, I've included the calculation for a 24-bit n, and the maximum 32-bit prime. My modest PC took ~13 seconds to calculate this. Check the answer against wolfram alpha, but beware that it may exceed the 'standard computation time' there.
There is still room for improvement if p is much smaller than (n-r) where r <= n-r. For example, we could precalculate all the inverses mod p instead of doing it on demand several times over.
nCr = n! / (r! * (n-r)!) {! = factorial}
now choose r or n - r in such a way that any of them is minimum
#include <cstdio>
#include <cmath>
#define MOD 10000007
int main()
{
int n, r, i, x = 1;
long long int res = 1;
scanf("%d%d", &n, &r);
int mini = fmin(r, (n - r));//minimum of r,n-r
for (i = n;i > mini;i--) {
res = (res * i) / x;
x++;
}
printf("%lld\n", res % MOD);
return 0;
}
it will work for most cases as required by programming competitions if the value of n and r are not too high
Time complexity :- O(min(r, n - r))
Limitation :- for languages like C/C++ etc. there will be overflow if
n > 60 (approximately)
as no datatype can store the final value..
The expansion of nCr can always be reduced to product of integers. This is done by canceling out terms in denominator. This approach is applied in the function given below.
This function has time complexity of O(n^2 * log(n)). This will calculate nCr % m for n<=10000 under 1 sec.
#include <numeric>
#include <algorithm>
int M=1e7+7;
int ncr(int n, int r)
{
r=min(r,n-r);
int A[r],i,j,B[r];
iota(A,A+r,n-r+1); //initializing A starting from n-r+1 to n
iota(B,B+r,1); //initializing B starting from 1 to r
int g;
for(i=0;i<r;i++)
for(j=0;j<r;j++)
{
if(B[i]==1)
break;
g=__gcd(B[i], A[j] );
A[j]/=g;
B[i]/=g;
}
long long ans=1;
for(i=0;i<r;i++)
ans=(ans*A[i])%M;
return ans;
}
I need to use pow in my c++ program and if i call the pow() function this way:
long long test = pow(7, e);
Where
e is an integer value with the value of 23.
I always get 821077879 as a result. If i calculate it with the windows calculator i get 27368747340080916343.. Whats wrong here? ):
I tried to cast to different types but nothing helped here... What could be the reason for this? How i can use pow() correctly?
Thanks!
The result is doesn't fit in long long.
If you want to deal with very big numbers then use a library like GMP
Or store it as a floating point (which won't be as precise).
Applying modulo:
const unsigned int b = 5; // base
const unsigned int e = 27; // exponent
const unsigned int m = 7; // modulo
unsigned int r = 1; // remainder
for (int i = 0; i < e; ++i)
r = (r * b) % m;
// r is now (pow(5,27) % 7)
723 is too big to fit into a long long (assuming it's 64 bits). The value is getting truncated.
Edit: Oh, why didn't you say that you wanted pow(b, e) % m instead of just pow(b, e)? That makes things a whole lot simpler, because you don't need bigints after all. Just do all your arithmetic mod m. Pubby's solution works, but here's a faster one (O(log e) instead of O(e)).
unsigned int powmod(unsigned int b, unsigned int e, unsigned int m)
{
assert(m != 0);
if (e == 0)
{
return 1;
}
else if (e % 2 == 0)
{
unsigned int squareRoot = powmod(b, e / 2, m);
return (squareRoot * squareRoot) % m;
}
else
{
return (powmod(b, e - 1, m) * b) % m;
}
}
See it live: https://ideone.com/YsG7V
#include<iostream>
#include<cmath>
int main()
{
long double ldbl = pow(7, 23);
double dbl = pow(7, 23);
std::cout << ldbl << ", " << dbl << std::endl;
}
Output: 2.73687e+19, 2.73687e+19
I'm trying to implement a simple RSA encryption/decryption process, and I'm pretty sure I've got the equations around the right way. Although it doesn't seem to be printing out the correct decrypted value after the encryption. Any ideas?.
//test program
#include <iostream>
#include <string.h>
#include <math.h>
using namespace std;
int gcd(int a, int b);
int main(){
char character = 'A'; //character that is to be encrypted
int p = 7;
int q = 5;
int e = 0; // just initializing to 0, assigning actual e value in the 1st for loop
int n = p*q;
int phi = (p-1)*(q-1);
int d = 0; // " " 2nd for loop
//---------------------------finding 'e' with phi. where "1 < e < phi(n)"
for (int i=2; i < phi; i++){
if (gcd(i,phi) == 1){ //if gcd is 1
e = i;
break;
}
}
//----------------------------
//---------------------------finding 'd'
for (int i = 2; i < phi; i++){
int temp = (e*i)%phi;
if (temp == 1){
d = i;
break;
}
}
printf("n:%d , e:%d , phi:%d , d:%d \n",n,e,phi,d);
printf("\npublic key is:[%d,%d]\n",e,n);
printf("private key is:[%d,%d]\n",d,n);
int m = static_cast<int>(character); //converting to a number
printf("\nconverted character num:%d\n",m);
//Encryption part ie. c = m^e MOD n
int power = pow(m,e); // m^e
int c = power%n; // c = m^e MOD n. ie. encrypted character
printf("\n\nEncrypted character number:%d\n",c);
//decryption part, ie. m = c^d MOD n
power = pow(c,d);
int m2 = power%n;
printf("\n\ndecrypted character number:%d\n",m2);
return 0;
}
int gcd(int a, int b){
int r;
if (a < 0) a = -a;
if (b < 0) b = -b;
if (b > a) {
r = b; b = a; a = r;
}
while (b > 0) {
r = a % b;
a = b;
b = r;
}
return a;
}
(The prime numbers being used are 5 and 7, for the test)
Here I'm converting the character 'A' to its numeric value which is of course 65. When I encrypt this value using c = m^e MOD n (where m is the converted value, i.e. 65) it gives me c as 25.
Now, to reverse the process, I do m = c^d MOD n, which gives me m as 30 ... which really isn't correct because it should be 65, no?
Where exactly have I gone wrong?
[edit]
Is my calculation of d correct?
The encrypted message m must be less than n. You can't use values larger than n, because the calculations are done modulo n. In your case m=65 and n=35. So you are actually getting the correct answer modulo n, because 65 % 35 == 30.
It is caused by having m greater than or equal to n like #interjay already answered.
But I found another problem with your code, my gcc4.1.2 compiler output 24 for the encrypted value not 25. It is because you use pow() function and then convert the result (which is type double) to int that causes precision loss.
Don't use pow() function, instead use square and multiply modulo n algorithm to compute c = m^e MOD n and m = c^d MOD n. It is faster than pow() and you won't need to unsafely downcast the result to integer.