osg*_*sgx 5 math gmp bignum arbitrary-precision chinese-remainder-theorem
我有一个长整数,但它不是以十进制形式存储,而是存储为余数.
所以,我没有这个N数字,而是一组这样的剩余部分:
r_1 = N % 2147483743
r_2 = N % 2147483713
r_3 = N % 2147483693
r_4 = N % 2147483659
r_5 = N % 2147483647
r_6 = N % 2147483629
Run Code Online (Sandbox Code Playgroud)
我知道,N小于这些素数的乘法,所以中文余数定理在这里起作用(http://en.wikipedia.org/wiki/Chinese_remainder_theorem).
N如果我有这6个余数,我怎么能以十进制恢复?精彩的将是任何程序(C/C + GMP/C++/perl/java/bc).
例如,最小N可以有这组余数:
r_1 = 1246736738 (% 2147483743)
r_2 = 748761 (% 2147483713)
r_3 = 1829651881 (% 2147483693)
r_4 = 2008266397 (% 2147483659)
r_5 = 748030137 (% 2147483647)
r_6 = 1460049539 (% 2147483629)
Run Code Online (Sandbox Code Playgroud)
您链接的文章已经提供了一个建设性的算法来找到解决方案.
基本上,每一个i你解决整数方程ri*ni + si*(N/ni) = 1哪里N = n1*n2*n3*....这里ri和si未知数.这可以通过扩展的欧几里德算法来解决.它非常受欢迎,您可以在任何语言中查找示例实现.
然后,假设ei = si*(N/ni),答案是sum(ei*ai)每个人i.
所有这些都在该文章中进行了描述,并附有证据和示例.
这里是代码(C+GMP),基于 Ben Lynn blynn@github 的 LGPL 代码;斯坦福大学的 Garner 算法(通过查询 garner mpz_t 通过 RIP Google 代码搜索找到): https://github.com/blynn/pbc/blob/master/guru/indexcalculus.c (他的 PBC(基于配对的加密货币)的一部分)图书馆)
编译用gcc -std=c99 -lgmp. 还可以根据您的情况更改尺寸。
#include <gmp.h>
#include <stdlib.h>
#include <stdio.h>
#include <malloc.h>
// Garner's Algorithm.
// See Algorithm 14.71, Handbook of Cryptography.
// x - result v residuals m - primes t-size of vectors
static void CRT(mpz_t x, mpz_ptr *v, mpz_ptr *m, int t) {
mpz_t u;
mpz_t C[t];
int i, j;
mpz_init(u);
for (i=1; i<t; i++) {
mpz_init(C[i]);
mpz_set_ui(C[i], 1);
for (j=0; j<i; j++) {
mpz_invert(u, m[j], m[i]);
mpz_mul(C[i], C[i], u);
mpz_mod(C[i], C[i], m[i]);
}
}
mpz_set(u, v[0]);
mpz_set(x, u);
for (i=1; i<t; i++) {
mpz_sub(u, v[i], x);
mpz_mul(u, u, C[i]);
mpz_mod(u, u, m[i]);
for (j=0; j<i; j++) {
mpz_mul(u, u, m[j]);
}
mpz_add(x, x, u);
}
for (i=1; i<t; i++) mpz_clear(C[i]);
mpz_clear(u);
}
const int size=6; // Change this please
int main()
{
mpz_t res;
mpz_ptr t[size], p[size];
for(int i=0;i<size;i++) {
t[i]=(mpz_ptr)malloc(sizeof(mpz_t));
p[i]=(mpz_ptr)malloc(sizeof(mpz_t));
mpz_init(p[i]);
mpz_init(t[i]);
}
mpz_init(res);
for(int i=0;i<size;i++){
unsigned long rr,pp;
scanf("%*c%*c%*c = %lu (%% %lu)\n",&rr,&pp);
printf("Got %lu res on mod %% %lu \n",rr,pp);
mpz_set_ui(p[i],pp);
mpz_set_ui(t[i],rr);
}
CRT(res,t,p,size);
gmp_printf("N = %Zd\n", res);
}
Run Code Online (Sandbox Code Playgroud)
示例已解决:
$ ./a.out
r_1 = 1246736738 (% 2147483743)
r_2 = 748761 (% 2147483713)
r_3 = 1829651881 (% 2147483693)
r_4 = 2008266397 (% 2147483659)
r_5 = 748030137 (% 2147483647)
r_6 = 1460049539 (% 2147483629)
Got 1246736738 res on mod % 2147483743
Got 748761 res on mod % 2147483713
Got 1829651881 res on mod % 2147483693
Got 2008266397 res on mod % 2147483659
Got 748030137 res on mod % 2147483647
Got 1460049539 res on mod % 2147483629
N = 703066055325632897509116263399480311
Run Code Online (Sandbox Code Playgroud)
N 是 703066055325632897509116263399480311