Chinese remainder theorem and the extended Chinese remainder theorem

TJOI2009 Guess

HDU 1573 X issue



Chinese Remainder Theorem CRT

The Chinese Remainder Theorem is used in solving linear equations of the same.
\ [\ Begin {aligned} \ left \ {\ begin {matrix} x \ equiv c_1 (mod \, \, m_1) \\ x \ equiv c_2 (mod \, \, m_2) \\ ... \\ x \ equiv c_n (mod \, \
, m_n) \ end {matrix} \ right. \ end {aligned} \] Chinese remainder theorem is coming.

Let's consider the following equations:
\ [\ the aligned the begin {} \ left \ {\} x_1 the begin {Matrix \ equiv. 1 (MOD \, \, m_1) \\ x_1 \ equiv 0 (MOD \, \, M_2 ) \\ ... \\ x_1 \ equiv 0 (mod \, \, m_n) \ end {matrix} \ right., \ left \ {\ begin {matrix} x_2 \ equiv 0 (mod \, \, m_1) \\ x_2 \ equiv 1 (mod \ , \, m_2) \\ ... \\ x_2 \ equiv 0 (mod \, \, m_n) \ end {matrix} \ right., \ left \ {\ begin {matrix } x_n \ equiv 0 (mod \ , \, m_1) \\ x_n \ equiv 0 (mod \, \, m_2) \\ ... \\ x_n \ equiv 1 (mod \, \, m_n) \ end {matrix .} \ right \ end {aligned
} \] then, in the \ (gcd (m1, m2, ..., m_n) \) when it is clear that the following conclusions:

If
\ [\ begin {aligned} \ prod_ {i \ neq 1} m_i x_1 '& \ equiv 1 (mod \, \, m_1) \\ \ prod_ {i \ neq 2} m_i x_2' & \ equiv 1 (mod \, \, m_2) \\ \
prod_ {i \ neq n} m_i x_n '& \ equiv 1 (mod \, \, m_n) \\ \ end {aligned} \] so
\ [\ begin {aligned} x_1 & = x_1 '\ prod_ {i \ neq 1} m_i \\ x_2 & = x_2' \ prod_ {i \ neq 2} m_i \\ x_n & = x_n '\ prod_ {i \ neq n} m_i \\ \ end {aligned } \]
then the final result is
\ [x = \ sum_ {i
= 1} ^ nc_ix_i + k \ prod_ {i = 1} ^ nm_i \] then the routine is better to write it.

TJOI2009 Guess

#include <bits/stdc++.h>
#define LL long long
using namespace std;

LL n;
LL A[ 20 ], B[ 20 ];
LL M, Ans, T[ 20 ];

LL QM( LL x, LL y ) {
    LL Ans = 0;
    for( ; y; y >>= 1, x = x * 2 % M ) 
        if( y & 1 ) Ans = ( Ans + x ) % M;
    return Ans;
}

void Expower( LL a, LL b, LL &x, LL &y ) {
    if( b == 0 ) {
        x = 1; y = 0; return;
    }
    Expower( b, a % b, y, x );
    y -= a / b * x;
    return;
}

LL INV( LL a, LL b ) {
    LL x, y;
    Expower( a, b, x, y );
    if( x < 0 ) x += b;
    return x;
}

int main() {
    scanf( "%lld", &n );
    for( LL i = 1; i <= n; ++i ) scanf( "%lld", &A[ i ] );
    for( LL i = 1; i <= n; ++i ) scanf( "%lld", &B[ i ] );
    for( LL i = 1; i <= n; ++i ) A[ i ] %= B[ i ];
    M = 1;
    for( LL i = 1; i <= n; ++i ) M *= B[ i ];
    for( LL i = 1; i <= n; ++i ) T[ i ] = QM( INV( M / B[ i ], B[ i ] ), ( M / B[ i ] ) );
    Ans = 0;
    for( LL i = 1; i <= n; ++i ) Ans = ( Ans + QM( A[ i ], T[ i ] ) ) % M;
    printf( "%lld\n", Ans );
    return 0;
}

Extended Chinese remainder theorem ExCRT

Just mentioned, Chinese remainder theorem applies to modulo relatively prime time. If the modulus is not relatively prime, then we need to use the extended Chinese remainder theorem.

ExCRT works like this:

First we observe two linear congruence equation:
\ [\ the aligned the begin {X} & \ equiv c_1 and (MOD \, \, m_1) X & \\ \ equiv c_2 (MOD \, \, M_2) \ the aligned End { } \]
we will write it in this form:
\ [\ the aligned the begin {X} + & k_1m_1 = c_1 and c_2 + = \\ X & k_2m_2 \ the aligned End {} \]
after simultaneous obtain:
\ [\ the aligned the begin { } c_1 + k_1m_1 & = c_2 +
k_2m_2 \\ \ Rightarrow k_1m_1-k_2m_2 & = c_2-c_1 \ end {aligned} \] Sufficient conditions prepared from Shu Pei theorem, equation solvability is \ (gcd (m_1, m_2) | (c_2-c_1) \) .

In this case, we can get:
\ [\ the begin {the aligned} & k_1 \ FRAC {m_1} {GCD (m_1, M_2)} - K_2 \ FRAC {M_2} {GCD (m_1, M_2)} = \ FRAC {c_2- c_1} {gcd (m_1, m_2 )} \\ \ Rightarrow & k_1 \ frac {m_1} {gcd (m_1, m_2)} \ equiv \ frac {c_2-c_1} {gcd (m_1, m_2)} \, \, ( mod \, \, \ frac { m_2} {gcd (m_1, m_2)}) \\ \ Rightarrow & k_1 \ equiv \ frac {c_2-c_1} {gcd (m_1, m_2)} \ times (\ frac {m_1} {gcd (m_1, m_2)}
) ^ {- 1} \, \, (mod \, \, \ frac {m_2} {gcd (m_1, m_2)}) \ end {aligned} \] then \ (k_1 \) substituting back \ (x = k_1m_1 \) c_1 + afford
\ [x \ equiv \ frac { c_2-c_1} {gcd (m_1, m_2)} \ times (\ frac {m_1} {gcd (m_1, m_2 )}) ^ {- 1}
\ times m_1 + c_2 \, \, (mod \, \, \ frac {m_2} {gcd (m_1, m_2)}) \] we have got a shape such as \ (X \ equiv c \, \, (mod \, \, m) \) linear congruence equation. So iterative solution can be.

HDU 1573 X issue

#include <bits/stdc++.h>
#define LL long long
using namespace std;

const int Maxm = 20;

void Work();

int main() {
    int TestCases;
    scanf( "%d", &TestCases );
    for( ; TestCases; --TestCases ) Work();
    return 0;
}

int N, M, A[ Maxm ], B[ Maxm ];
struct equation {
    LL A, B;
};
equation T1, T2;

LL GCD( LL x, LL y ) {
    LL m = x % y;
    while( m ) {
        x = y; y = m; m = x % y;
    }
    return y;
}

void ExGCD( LL a, LL b, LL &x, LL &y ) {
    if( b == 0 ) {
        x = 1; y = 0; return;
    }
    ExGCD( b, a % b, y, x );
    y -= a / b * x;
    return;
}

LL Inv( LL a, LL b ) {
    LL x, y;
    ExGCD( a, b, x, y );
    if( x < 0 ) x += b;
    return x;
}

equation ExCRT( equation X, equation Y ) {
    LL Gcd = GCD( X.A, Y.A );
    if( ( Y.B - X.B ) % Gcd ) return ( equation ) { 0, 0 };
    LL A = X.A * Y.A / Gcd;
    LL B = Inv( X.A / Gcd, Y.A / Gcd ) * ( Y.B - X.B ) / Gcd % ( Y.A / Gcd ) * X.A + X.B;
    return ( equation ) { A, B };
}

void Work() {
    scanf( "%d%d", &N, &M );
    for( int i = 1; i <= M; ++i ) scanf( "%d", &A[ i ] );
    for( int i = 1; i <= M; ++i ) scanf( "%d", &B[ i ] );
    T1 = ( equation ) { A[ 1 ], B[ 1 ] };
    for( int i = 2; i <= M; ++i ) {
        T2 = ( equation ) { A[ i ], B[ i ] };
        T1 = ExCRT( T1, T2 );
        if( !T1.A ) {
            printf( "0\n" );
            return;
        }
    }
    if( T1.B < 0 ) T1.B += T1.A;
    if( T1.B > N ) {
        printf( "0\n" );
        return;
    }
    if( T1.B ) printf( "%d\n", ( int ) ( ( N - T1.B ) / T1.A + 1 ) ); 
    else printf( "%d\n", ( int ) ( N / T1.A ) );
    return;
}

Guess you like

Origin www.cnblogs.com/chy-2003/p/11458559.html