void pre_compute() { for(int i = 0; i < MAX; ++i) { invp[i] = mod_inverse(i, MOD); } for(int i = 0; i < MAX; ++i) { invp2[i] = mod_inverse(MOD-i, MOD); } }
void generateKeys(long a, long b, long *e, long *d, long *c) { while((*c < 2) || (*c > 10000) || (*e < 2) || (*e > 10000) || (*d < 2) || (*d > 10000)) { *c = a * b; *e = coprime( (a - 1) * (b - 1)); *d = mod_inverse(*e, ((a - 1) * (b - 1))); } }
// nCk mod p ; O(log_p n) // nCk = n! / (k!(n-k)!) int mod_comb(int n, int k, int p){ if (n<0 || k<0 || n<k) return 0; int e1, e2, e3; int a1 = mod_fact(n, p, e1), a2 = mod_fact(k, p, e2), a3 = mod_fact(n-k, p, e3); if (e1 > e2+e3) return 0; // nCk is divided by p return a1 * mod_inverse(a2 * a3 % p, p) % p; }
//Uses Lagrange interpolation method //Complexity : O(klog k) inline int summation(long long n, int k) { int sum = 0; vals.push_back(sum); for(int i = 0; i <= k; ++i) { sum = add(sum , power(i + 1, k, MOD), MOD); vals.push_back(sum); } if (n < vals.size()) return vals[n]; n %= MOD; int ans = 0; int store = 1, temp; // Lagrange interpolation pre-computation for(int j = 1; j < vals.size(); ++j) { store = mul(store, mod_neg(n, j, MOD), MOD); store = mul(store, invp2[j], MOD); } for(int i = 0; i < vals.size(); ++i) { ans = add(ans, mul(vals[i], store, MOD), MOD); temp = mul(mod_neg(n, i, MOD), mod_inverse(mod_neg(n, (i + 1), MOD), MOD), MOD); store = mul(store, temp, MOD); temp = mul(mod_neg(i, ((int)vals.size() - 1), MOD), invp[i + 1], MOD); store = mul(store, temp, MOD); } return ans; }
long long chinese_remainder(vector <long long> ar, vector <long long> mods){ long long x, y, res = 0, M = 1; for (int i = 0; i < ar.size(); i++) M *= mods[i]; for (int i = 0; i < ar.size(); i++){ x = M / mods[i], y = mod_inverse(x, mods[i]); res = (res + (((x * ar[i]) % M) * y)) % M; } return res; }
// computes x and y such that ax + by = c; on failure, x = y =-1 void linear_diophantine(int a, int b, int c, int &x, int &y) { int d = gcd(a,b); if (c%d) { x = y = -1; } else { x = c/d * mod_inverse(a/d, b/d); y = (c-a*x)/b; } }
//A[i] * x % M[i] = B[i]; std::pair<int, int> linear_congruence(const std::vector<int> &A, const std::vector<int> &B, const std::vector<int> &M) { int x = 0, m = 1; for(int i = 0; i < A.size(); i++) { int a = A[i] * m, b = B[i] - A[i] * x, d = gcd(M[i], a); if(b % d != 0) return std::make_pair(0, -1); // no solutioin int t = b / d * mod_inverse(a / d, M[i] / d) % (M[i] / d); x = x + m * t; m *= M[i] / d; } x = (x + m) % m; return std::make_pair(x % m, m); }
void main() { srand(time(NULL)); char *input = "Hello"; int *encOutput = (int *)malloc(sizeof(int) * strlen(input) + 1); int c = 13 * 17; int i; int a = 13; int b = 17; int e = coprime(12 * 16); int m = totient(13 * 17); int d = mod_inverse(e, 12 * 16); printf("totient = %d", totient(13 * 17)); printf("e = %d\n", coprime(12 * 16)); printf("d = %d\n", mod_inverse(coprime(12 * 16), 12 * 16)); int enc = encrypt(50, e,c); int dec = decrypt(enc, d, c); printf("enc = %d\n", enc); printf("dec = %d\n", dec); for(i = 0; i < strlen(input); i++) { encOutput[i] = encrypt(input[i], e, c); } printf("Hello has been translated into %d %d %d %d %d\n", encOutput[0], encOutput[1], encOutput[2], encOutput[3], encOutput[4]); // printf("coprime=%d\n",mod_inverse(3, 30)); //printf("%d", modulo(2349723,423424,12345)); //printf("mod inv = %d\n", extendedEuclid(442, 2278, &d, &x, &y)); //printf("d = %d \t x = %d \t y = %d\n", d,x,y); //coprime(5); }
T chinese_remainder_theorem(const std::vector<T>& a, const std::vector<T>& m) { auto solve2 = [](T a0, T m0, T a1, T m1) { T t = mod_inverse(m0 % m1, m1); assert(t != m1); // Otherwise no solution exists. t = mod_mul(mod_sub(a1, a0 % m1, m1), t, m1); return std::make_pair(a0 + m0 * t, m0 * m1); }; std::pair<T, T> reduced{a[0], m[0]}; for (size_t i = 1; i < a.size(); ++i) { reduced = solve2(reduced.first, reduced.second, a[i], m[i]); assert(reduced.first >= 0 && reduced.first < reduced.second); } return reduced.first; }
void generate() { for(int i = 0; i < MAX; ++i) { invp[i] = mod_inverse(i, MOD); } S[0][0] = 1; for (int i = 1; i < MAX; ++i) { S[i][0] = 0; for (int j = 1; j <= i; ++j) { S[i][j] = mod((long long)S[i - 1][j] * j, (long long)MOD); S[i][j] = add(S[i][j], S[i-1][j-1], MOD); } } for(int i = 1; i < MAX; ++i) { for(int j = 1; j <= i; ++j) { S[i][j] = mod((long long)S[i][j] * invp[j + 1], (long long)MOD); } } }
void generateKeys(long a, long b, long *e, long *d, long *c) { *c = a * b; *e = coprime( (a - 1) * (b - 1)); *d = mod_inverse(*e, ((a - 1) * (b - 1))); }