5

私は長整数を持っていますが、10進数ではなく、剰余のセットとして格納されています。

だから、私は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

Nはこれらの素数の乗算よりも小さいので、中国の剰余定理はここで機能します(http://en.wikipedia.org/wiki/Chinese_remainder_theorem)。

Nこの6つの余りがある場合、10進数で復元するにはどうすればよいですか?これを行うためのプログラム(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)
4

3 に答える 3

6

リンクする記事は、解決策を見つけるための建設的なアルゴリズムをすでに提供しています。

基本的に、それぞれについてi整数方程式を解きます。ri*ni + si*(N/ni) = 1ここでN = n1*n2*n3*...riとはここでsiは不明です。これは、拡張ユークリッドアルゴリズムによって解決できます。これは非常に人気があり、どの言語でもサンプル実装を見つけるのに問題はありません。

次に、を仮定ei = si*(N/ni)すると、答えはsum(ei*ai)すべてに対してiです。
これはすべて、その記事で証明と例とともに説明されています。

于 2011-03-13T02:10:00.790 に答える
2

ここに、Ben Lynn blynn @ githubによるこのLGPLコードに基づくコード(C + GMP)があります。スタンフォードオブガーナーアルゴリズム(クエリガーナー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);
}

例は解決されました:

$ ./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

Nは703066055325632897509116263399480311です

于 2011-03-13T05:49:49.197 に答える
1

これは、このロゼッタコードタスクに基づくPython 3の実装です:https ://rosettacode.org/wiki/Chinese_remainder_theorem

from functools import reduce
from operator import mul    

def chinese_remainder(n, a):
    """
    Chinese Remainder Theorem.

    :param n: list of pairwise relatively prime integers
    :param a: remainders when x is divided by n
    """
    s = 0
    prod = reduce(mul, n)
    for n_i, a_i in zip(n, a):
        p = prod // n_i
        s += a_i * inverse(p, n_i) * p
    return s % prod    

def inverse(a, b):
    """
    Modular multiplicative inverse.
    """
    b0 = b
    x0, x1 = 0, 1
    if b == 1:
        return 1
    while a > 1:
        q = a // b
        a, b = b, a % b
        x0, x1 = x1 - q * x0, x0
    if x1 < 0:
        x1 += b0
    return x1    

n = [2147483743, 2147483713, 2147483693, 2147483659, 2147483647, 2147483629]
a = [1246736738, 748761, 1829651881, 2008266397, 748030137, 1460049539]

print(chinese_remainder(n, a))  # 703066055325632897509116263399480311

Pythonの優れた機能は、任意の大きさの整数を自然にサポートすることです。

于 2019-04-21T07:57:01.317 に答える