LightOJ 1319 Monkey Tradition

Solution
\ [x \ equiv \ left \
{\ begin {aligned} a_1 \ mod p_1 \\ a_2 \ mod p_2 \\ ... \\ a_n \ mod p_n \ end {aligned} \ right. \] Wherein \ (P_i \) is a prime number

If positive integer solution, the minimum output, and if not, the output Impossible


Front cheese:

\ (exgcd \) seeking multiplicative inverse

That is to say, seeking \ (X \) such that \ (ax \ equiv 1 \ mod b \)

Corresponds seeking \ (ax = kb + 1 \ )

Transposition
\ [ax-kb = 1 \
] provided \ (Y = -k \)
\ [= AX +. 1 by \]
This significant thing \ (exgcd \) can engage them

Then started

Chinese remainder theorem \ ((the CRT) \)
\ [X \ equiv \ left \ {\ the aligned the begin {A_1} \ \\ MOD P_1 A_2 \ \\ ... \\ MOD P_2 A_N \ MOD P_n \ the aligned End {} \ right. \]
provided \ (M = p_1 * p_2 * ... * p_n, m_i = \ frac {M} {p_i} \)

Since \ (p_i \) is a prime number, so \ ([0, M-1 ] \) have the range of one and only one solution (the own emotional understanding will know)

So we just an arbitrary solution, then it \ (M \) taken like membrane

We assume that
\ [ans_i \ equiv \ left \
{\ begin {aligned} a_i \ mod p_i \\ 0 \ mod m_i \ end {aligned} \ right. \] Then the \ (ans_i \) he do anything extraordinary ? It just satisfies \ (\ equiv a_i \ mod p_i \) and does not "affect" the other \ (a_j, p_j \)

The answer is $ ans = \ sum_ {i = 1} ^ nans_i% M $

So how do we find $ ans_i $?

First of all, \ (ans_i \) is (m_i \) \ multiples, so we set \ (ans_i = k_i * m_i \ )

Then we have to allow him to meet \ (\ equiv a_i \ MOD P_i \) , then we set \ (k_i = a_i * t_i \ )

That \ (ans_i = m_i * a_i * t_i \)

We want
\ [m_i * t_i \ equiv 1
\ mod p_i \] is seeking a \ (m_i \) in \ (\ mod p_i \) multiplicative inverse in the sense of the thing, \ (exgcd \) wave

Is then calculated for each \ (ans_i \) plus one plus taken membranes, did not

Time complexity \ (O (nlog M) \ )

// This code Write By chtholly_micromaker(MicroMaker)
#include <cstdio>
#include <cctype>
#define int long long
#define reg register
using namespace std;
const int MaxN=15;
template <class t> inline void rd(t &s)
{
    s=0;
    reg char c=getchar();
    while(!isdigit(c))
        c=getchar();
    while(isdigit(c))
        s=(s<<3)+(s<<1)+(c^48),c=getchar();
    return;
}
inline int exgcd(int a,int b,int &x,int &y)
{
    if(!b)
    {
        x=1,y=0;
        return a;
    }
    reg int c=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return c;
}
int n,mulsum;
int a[MaxN],p[MaxN];
inline int crt()
{
    reg int ans=0,mi,x,y;
    for(int i=1;i<=n;++i)
    {
        mi=mulsum/p[i];
        exgcd(p[i],mi,x,y);
        ans=(ans+a[i]*mi*y)%mulsum;
    }
    return (ans+mulsum)%mulsum;
}
inline void work()
{
    mulsum=1;
    rd(n);
    for(int i=1;i<=n;++i)
    {
        rd(p[i]);rd(a[i]);
        mulsum*=p[i];
    }
    printf("%lld\n",crt());
    return;
}
signed main(void)
{
    int t;rd(t);
    for(int i=1;i<=t;++i)
        printf("Case %lld: ",i),work();
    return 0;
}

Guess you like

Origin www.cnblogs.com/chinesepikaync/p/12301060.html
Recommended