int main() { ll x, y, m, n, L, a, b, c, r, p, q, t; while(~scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &L)) { b = L; a = n-m; c = x-y; r = gcd(a, b); if(c%r) { printf("Impossible\n"); continue; } extended_euclid(a, b, p, q); // x = x0 + b/gcd(a,b)*t // y = y0 - a/gcd(a,b)*t // t is integer. // Calculate how many b in c*p/r at most.(c*p/r is x in ax+by=c) // should notice that t*b <= y t = c*p/r/b; // Get a particular solution which x is the smallest in all solutions. p = c*p/r - t*b; if(p<0) p += b; printf("%lld\n", p); } return 0; }
/* Euclid's Extended GCD algorithm to compute the modular inverse of an element */ void extended_euclid(long int A1, long int A2, long int A3, long int B1, long int B2,long int B3) { long int Q; long int T1,T2,T3; if(B3==0){ gcd_value= A3; mul_inverse= NOT_EXIST; return; } if(B3==1){ gcd_value= B3; mul_inverse= B2; return; } Q=(int)(A3/B3); T1=A1-Q*B1; T2=A2-Q*B2; T3=A3-Q*B3; A1=B1; A2=B2; A3=B3; B1=T1; B2=T2; B3=T3; extended_euclid(A1,A2,A3,B1,B2,B3); }
int main(void) { long a = 4864, b = 3458, d, x, y; extended_euclid(a, b, &x, &y, &d); printf("x = %ld y = %ld d = %ld\n", x, y, d); return 0; }
long inverse(long a, long n) /* computes the inverse of a modulo n */ { long d, x, y; extended_euclid(a, n, &x, &y, &d); if (d == 1) return x; return 0; }
// finds all solutions to ax = b (mod n) ve<int> modular_linear_equation_solver(int a, int b, int n) { int x, y; ve<int> solutions; int d = extended_euclid(a, n, x, y); if (!(b%d)) { x = mod (x*(b/d), n); for (int i = 0; i < d; i++) solutions.push_back(mod(x + i*(n/d), n)); } return solutions; }
i64 find_inv(i64 a, i64 prime) { i64 x, y, g; extended_euclid(a, prime, x, y, g); assert(g == 1); if(x < 0) x += prime; assert( x > 0 && x < prime); assert((a*x) % prime == 1); return x; }
ll extended_euclid(ll a, ll b, ll &x, ll &y) { if(b==0) { x=1,y=0; return a; } ll x1,y1; ll ret=extended_euclid(b,a%b,x1,y1); x=y1; y=x1-y1*(a/b); return ret; }
int main(int argc, char **argv){ int i,j, r_size; unsigned long long tmp1, tmp2; unsigned long long p, q, e, d; unsigned long long phi, n, nn, num, encoded_num; unsigned long long buf; FILE *fid_keys; int fid_in, fid_out, r_count; fid_in = open(argv[1], O_RDONLY); fid_out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 00755); if (strcmp(argv[3], "1") == 0){ /*1 -- encode 0 - decode*/ fid_keys = fopen("keys", "w"); p = prime(); q = prime(); n = p*q; while (n >= MAXN){ p = prime(); q = prime(); n = p*q; } phi = (p-1)*(q-1); e = prime_too(phi); extended_euclid(e, phi, &d, &tmp1, &tmp2); d = d % phi; fprintf(fid_keys, "Secret key: %llu-%llu\nPublic key: %llu-%llu\n", d, n, e, n); }else{ fid_keys = fopen("keys", "r"); if (fscanf(fid_keys, "Secret key: %llu-%llu\nPublic key: %llu-%llu\n", &d, &n, &e, &n) < 4){puts("Make keys with param 1 first."); exit(0);}; } nn = 1; r_size = 0; while (nn <= n) {nn <<= 8; r_size++;}; r_size -= 1; if (r_size <= 0){puts("Error: Too small p, q. p*q must be bigger than 255."); exit(0);} printf("%d\n", r_size); if (strcmp(argv[3], "1") == 0){ while (r_count = read(fid_in, num, r_size) > 0){ encoded_num = crypt(num, d, n); printf("%llu\n", encoded_num); write(fid_out, ((char *)(&encoded_num)) + sizeof(unsigned long long) - r_count, r_count); } }else{ while (r_count = read(fid_in, num, r_size) > 0){ num = crypt(encoded_num, e, n); write(fid_out, ((char *)(&num)) + sizeof(unsigned long long) - r_count, r_count); } } if (close(fid_in) < 0){perror("fid_in"); exit(0);}; if (close(fid_out) < 0){perror("fid_out"); exit(0);}; fclose(fid_keys); return 0; }
void extended_euclid(ll a, ll b, ll &x, ll &y) { if(b==0) { x=1; y=0; return; } extended_euclid(b, a%b, x, y); ll t = x; x = y; y = t - a/b*y; return; }
/* Determine the value that combined with string hashes to 0 */ static char hash_zero(int *coeffs, char *string, int size, int c) { gcd euclid = extended_euclid(size, coeffs[c]); // euclid.y + size to ensure it's positive euclid.y = (euclid.y + size) % size; // Get the hash of string excluding the char at c int hash = universal_hash((unsigned char*)string, size); hash -= coeffs[c] * (unsigned char) string[c] % size; // size is prime so euclid.y * coeffs % size = 1 // So hash + (size - hash) * 1 = size % size = 0 return (size - hash) * euclid.y % size; }
int extended_euclid(int a, int b, int& x, int& y) {//返回a,b的最大公约数以及a,b的系数x和y //使得等式gcd(a, b) = d = ax + by成立 //递归终止条件 if(b == 0){ int gcd = a; x = 1; y = 0; return(gcd); } int gcd = extended_euclid(b, a % b, x, y); int tmp = x; x = y; y = tmp - (a / b) * y; return(gcd); }
//KEY GENERATION ALGORITHM IN RSA CRYPTOSYSTEM. void KeyGeneration(key *pub_key, key *pvt_key) { long int p,q; long int n; long int phi_n; long int e; // Select p and q which are primes and p<q. if(print_flag1) printf("\n selecting p->\n\r"); while(1) { srand((unsigned int) time(NULL)); p = random() % LARGE; /* test for even number */ if ( p & 0x01 == 0 ) continue; if(MillerRobinTest(p, MAX_ITERATION)) break; } if(print_flag1) printf("\n selecting q->\n\r"); while(1) { srand((unsigned int) time(NULL)); q=random() % LARGE; if( q == p) { srand((unsigned int) time(NULL)); q = random() % LARGE; continue; } if(MillerRobinTest(q, MAX_ITERATION)) break; } // Compute n. if (verify_prime(p) && verify_prime(q) ) printf("p = %ld, q = %ld are primes\n", p, q); else { //exit(0); return recall_key(pub_key, pvt_key); } printf("p = %ld, q = %ld\n", p, q); n = p * q; // Compute Euler's phi(totient) function phi_n = (p-1)*(q-1); // Compute e such that gcd(e,phi_n(n))=1. if(print_flag1) printf("\n selcting e->\n\r"); while(1) { e = random()%phi_n; if(gcd(e, phi_n)==1) break; } // Compute d such that ed=1(mod phi_n(n)). if(print_flag1) printf("\n selceting d->\n\r"); extended_euclid(1, 0, phi_n, 0, 1, e); if(mul_inverse <0) { mul_inverse = - mul_inverse; mul_inverse = ((phi_n - 1 ) * mul_inverse) mod phi_n; } if(print_flag1) printf("\n phi_n= %ld\n\n",phi_n); // Put Public Key and Private Key. pub_key->public_key.n = n; pub_key->public_key.e = e; pvt_key->private_key.n = n; pvt_key->private_key.d = mul_inverse; } // end of KeyGeneraion()
int main() { //n= 100; m = 10; p = 4; i64 p1k = 1; i64 p1kinv = 0; for(i64 k = 2; k <= p; ++k){ p1k *=k; p1k%=nmod; } i64 nr = n % nmod; //630000 i64 mr = m % nmod; //63000 assert(mr < nr); vector<i64> v1, v2; v1.resize(15000, 0); v2.resize(15000, 0); vector<i64> vnum; vector<i64> vden; vnum.resize(nr-p, 1); vden.resize(nr-p, 0); // k= p to nr - 1, cannot have k = nr i64 prod = 1; for(i64 kk=0; kk<p; ++kk ) prod = product_mod(prod, n-kk, nmod); for(i64 kk = 0; kk<(i64)vnum.size(); ++kk){ vnum[kk] = prod; prod = product_mod(prod, n-p-kk, nmod); } prod = 1; vden[0] = 1; i64 x, y, gcd; for(i64 kk = 1; kk <= (i64)vden.size(); ++kk){ prod = product_mod(prod, kk, nmod); extended_euclid(prod, nmod, x, y, gcd); vden[kk] = x; //actuallly it has been inversed!!! } assert(product_mod(2LL, vden[2], nmod)== 1); assert(product_mod(6LL, vden[3], nmod)== 1); prod = 1; v1[0] = 1; for( i64 i = 1, t = n/nmod; t > 0; --t, ++i){ prod = product_mod(prod, t, nmod); v1[i] = prod; } prod = 1; v2[0] = 1; for(i64 t = 1; t <= n/nmod; ++t){ prod = product_mod(prod, t, nmod); extended_euclid(prod, nmod, x, y, gcd); v2[t] = x;//inversed!!!! } extended_euclid(p1k,nmod, p1kinv, y, gcd);//calculate p1kinv i64 kpart =0; i64 kpart2 = 0; for(i64 kk = 0; kk < (i64)vden.size(); ++kk ){ i64 t = product_mod(vden[kk], vnum[kk], nmod ); kpart += kk & 1 ? -t:t; kpart %= nmod; //printf("kk=%lld, num=%lld den=%lld t=%lld kpart=%lld sum=%lld\n", kk,vnum[kk], vden[kk], t, kpart, product_mod( p1kinv, kpart, nmod)); if(kk==mr-p-1) kpart2 = kpart; } i64 jpart = 0; i64 jt = 1; i64 t = 0; i64 sign = -1; i64 nseg = (m/nmod); //k = 0...nseg *nmod+(0, 630000) for(int j = 0; j < nseg; ++j){ t = product_mod(v1[j], v2[j], nmod); jt = product_mod(jt, t, nmod); sign = -sign; jpart += jt*sign; jpart %= nmod; } i64 sum = product_mod(jpart, kpart, nmod) + sign * product_mod(kpart2, jt, nmod); sum = product_mod(sum , p1kinv, nmod); printf("jpart=%lld kpart=%lld kpart2=%lld jt=%lld %lld\n",jpart, kpart, kpart2, jt, sum); }
int main(int argc, char **argv){ unsigned long long i,j; unsigned long long tmp1, tmp2, r_size; unsigned long long p, q, e, d, a; unsigned long long phi, n, nn, num, encoded_num; unsigned long long buf; FILE *fid_keys; int fid_in, fid_out, r_count; fid_in = open(argv[1], O_RDONLY); fid_out = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 00755); if (strcmp(argv[3], "1") == 0){ /*1 -- encode 0 - decode*/ #ifdef DEBUG printf("Start encode equations.\n"); #endif fid_keys = fopen("keys", "w"); p = prime(); q = prime(); n = p*q; phi = (p-1)*(q-1); e = prime_too(phi); extended_euclid(e, phi, &d, &tmp1, &tmp2); d = d % phi; #ifdef DEBUG printf("Variables:\n p: %llu, q: %llu, n: %llu\n phi: %llu, e: %llu\n d: %llu\n=====\n", p, q, n, phi, e, d); printf("Secret key: %llu-%llu\nPublic key: %llu-%llu\n", d, n, e, n); printf("=========\nStop encode equations\n"); #endif fprintf(fid_keys, "Secret key: %llu-%llu\nPublic key: %llu-%llu\n", d, n, e, n); }else{ #ifdef DEBUG printf("Start decode equations.\n"); #endif fid_keys = fopen("keys", "r"); if (fscanf(fid_keys, "Secret key: %llu-%llu\nPublic key: %llu-%llu\n", &d, &n, &e, &n) < 4){puts("Make keys with param 1 first."); exit(0);}; #ifdef DEBUG printf("Variables:\n n: %llu\n e: %llu\n d: %llu\n=====\n", n, e, d); printf("Secret key: %llu-%llu\nPublic key: %llu-%llu\n", d, n, e, n); printf("=========\nStop decode equations\n"); #endif } nn = 1; r_size = 0; while (nn <= n) {nn <<= 8; r_size+=1;}; r_size -= 1; if (r_size <= 0){puts("Error: Too small p, q. p*q must be bigger than 255."); exit(0);} printf("%d\n", r_size); if (strcmp(argv[3], "1") == 0){ while (r_count = read(fid_in, num, r_size) > 0){ encoded_num = crypt(num, d, n); printf("%llu\n", encoded_num); write(fid_out, ((char *)(&encoded_num)) + sizeof(unsigned long long) - r_count, r_count); } }else{ while (r_count = read(fid_in, num, r_size) > 0){ num = crypt(encoded_num, e, n); write(fid_out, ((char *)(&num)) + sizeof(unsigned long long) - r_count, r_count); } } if (close(fid_in) < 0){perror("fid_in"); exit(0);}; if (close(fid_out) < 0){perror("fid_out"); exit(0);}; fclose(fid_keys); return 0; }
/* Print n strings that are hashed to 0 by universal_hash seeded with seed */ void collide_clever(unsigned int size, unsigned int seed, int n) { const int MAX_SIZE = 10; srand(seed); fprintf(stdout, "%d\n", MAXSTRLEN); int r[MAXSTRLEN] = { -1 }; //Print out all the r values size_t i; if(r[0] == -1){ for(i = 0; i < MAXSTRLEN; i++) { r[i] = rand()%size; fprintf(stdout, "%d\n", r[i]); } } //Haven't really tested for large n values, as the requirements state full marks for n=2; //Currently I have n =10, which is satisfactory. if(n > MAX_SIZE) { fprintf(stdout, "Unknown results at n > %d, (n = %d was chosen) exiting...", MAX_SIZE, n); return; } char* keys[n]; int j; for(j = 0; j < n; j++) { long x, y, d; extended_euclid(r[j], size, &x, &y, &d); keys[j] = malloc(n* sizeof(char*)); //We don't like these ASCII characters, so don't use them while(x < 33) x += size; //if r[j] is zero it will always hash to 0, don't //need to find the zero mod if(r[j]!=0) x = x*r[j]-1; //We want x to be a char, therefore it must be less than MAXSTRLEN while(x > MAXSTRLEN) x -= size; //malloc the key everytime to ensure we get a new string char* key = (char*)malloc(2 * sizeof(char)); //Copy the previous string into the new one, then concatenate the //current string if(j>0) { //If we are on the second string, then concatenate the first string, to produce strings of significant length. key[0] = x; key[1] = '\0'; strcpy(keys[j], keys[j-1]); strcat(keys[j],key); } else { key[0] = x; key[1] = '\0'; keys[j] = key; } //This loop checks to see if we can generate anymore ASCII characters without having to increase our length by 1. //Not really part of the requirements but is still nice to have, so we don't always end up generating the same ASCII character //each time we increase the string length. while((x - size) >= 33 && (j +1) < n) { x-= size; j++; char* key = (char*)malloc(2 * sizeof(char)); keys[j] = malloc(10 * sizeof(char*)); key[0] = x; key[1] = '\0'; strcpy(keys[j], keys[j-1]); strcat(keys[j],key); } } for(j = 0 ; j < n; j++) { fprintf( stdout, "%s\n", keys[j]); } }
// find z such that z % x = a, z % y = b. Here, z is unique modulo M = lcm(x,y). // Return (z,M). On failure, M = -1. pii chinese_remainder_theorem(int x, int a, int y, int b) { int s, t; int d = extended_euclid(x, y, s, t); if (a%d != b%d) return make_pair(0, -1); return make_pair(mod(s*b*x+t*a*y,x*y)/d, x*y/d); }
// computes b such that ab = 1 (mod n), returns -1 on failure int mod_inverse(int a, int n) { int x, y; int d = extended_euclid(a, n, x, y); if (d > 1) return -1; return mod(x,n); }
template<typename T> T mod_inverse(T a, T n){T x,y;T d = extended_euclid(a, n, x, y);return (d>1?-1:mod_neg(x,n));}