Chinese remainder theorem to expand learning summary

Foreword

Saying good Chinese Remainder Theorem will be long, but the wood has been exposed to expand.
Only that it is what stuff.
Recently seem to need it, and learn a little science, it seems pretty simple.
Summary about ~

Brief introduction

Chinese remainder theorem we know everything, right?
While it is expanding back into a non-modulo a prime number (of course, the various equations modulo prime).
Solutions x is then determined minimum.

practice

After the expansion seems to be difficult to carry out his original routine.
How to do?
We found that we can use some weird push to merge persimmon persimmon Dafa.

Consider merging about two persimmon:
\ (the X-\ equiv c1 (MOD \ M1) \)
\ (the X-\ equiv c2 (MOD \ M2) \)
transformed it:
\ (the X-c1 + M1 = K1 * \)
\ (the X- = + m2 * k2 \) c2
combined transposition
\ (m1 * k1 = c2-
c1 + m2 * k2 \) disposed \ (g = gcd (m1,
m2) \) persimmon both sides with inter g obtained:
\ (\ frac {m1} g * k1 =
\ frac {c2-c1} g + \ frac {m2} g * k2 \) we consider conversion at:
\ (\ FRAC {M1} G * K1 \ equiv \ FRAC {C2-C1} g (mod \ \ frac {m2
} g) \) of course, this time we found, \ (\ FRAC c2-c1} {G \) this must be a persimmon integer, decimal otherwise there is a judgment about.
So, now that we have removed a k2, but the left is still very beautiful, the next wave of considering simplification.
Set \ (ny () \) represents the inverse yuan.
\ (K1 \ equiv NY (\ FRAC {M1} G) * \ FRAC {C2-C1} G (MOD \ \ FRAC {M2} G) \)
\ (K1 = NY (\ FRAC {M1} G) * \ frac g + \ frac {m2}
g * y \) {c2-c1} remember this persimmon it?
\ (x = c1 + m1 *
k1 \) so we put\ (K1 \) with back
\ (x = c1 + ny (
\ frac {m1} g) * \ frac {c2-c1} g * m1 + \ frac {m2 * m1} g * y \) removing y becomes : \
(the X-\ equiv c1 + ny (\ FRAC {M1} G) * \ FRAC c2-c1} {G * M1 (MOD \ \ FRAC M2 * M1} {G) \)
not to implement the merger it?
Then inverse solver can use our expanded Euclid.
Of course, the point to note is: be careful burst longlong, may need to use the turtle speed ride.

application

:( A recent example of a)
Comet OJ - # 10 Contest The fish big splash
Here Insert Picture Description
Here Insert Picture Description
how to do?
N to consider a prime factor decomposition.
\ (n = q_1 ^ {p_1
} * q_2 ^ {p_2} * ...... * q_m ^ {p_m} \) Consider the case of m = 1:
X can only be: \ (^ Y * q_m P_m} {\) or is a \ (y * q_m ^ {p_m
} -1 \) then the number can not exceed 12 m.
Therefore, we consider the direct enumeration of each Accession factor \ (y * q_m ^ {p_m } \) or \ (^ Y * q_m P_m} -1 {\) .
Then simultaneous equations, to expand the use of the Chinese remainder theorem can be solved.
Time complexity: \ (O (2 ^ 12 * 12 * log) \)
then the goose that problem than the relatively funny is that this approach will burst longlong, then we would hit the turtle-speed ride.
And there are very tight time, so to Kaka often.
This is why my game T did not cut out 17 reasons QWQ.

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

int t;
long long zs[1000011],bz[1000011],p[1000011],flag[1000011];
long long n,x,y,gs,mi[21],m[21],c[21],ans;
bool bzz;

long long gcd(long long a,long long b)
{
    if (b==0) return a;
    else return gcd(b,a%b);
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
    if (b==0)
    {
        x=1;y=0;return a;
    }
    else
    {
        long long d=a/b; 
        long long c=exgcd(b,a-b*d,x,y);
        long long z=x;
        x=y;y=z-d*y;
        return c;
    }
}
long long ny(long long a,long long b)
{
    long long z=exgcd(a,b,x,y);
    while (x<0)
    {
        x+=b;
    }
    return x;
}

long long cheng(long long a,long long b,long long mo)
{
    long long t=0;
    while(b)
    {
        t=(t+a*(b&1023))%mo;
        b>>=10;
        a=a*1024%mo; 
    }
    return t;
}

#define R register
int main()
{
    mi[0]=1;
    for (int i=1;i<=20;i++)
    {
        mi[i]=mi[i-1]*2;
    }
    for (int i=2;i<=1000000;i++)
    {   
        if (bz[i]==0)
        {
            zs[0]++;
            zs[zs[0]]=i;
            for (int j=1;j*i<=1000000;j++)
            {
                bz[j*i]=1;
            }
        }
    }
    scanf("%d",&t);
    while (t>0)
    {
        t--;
        scanf("%lld",&n);
        if (n==1)
        {
            printf("1\n");
            continue;
        }
        long long j=0;
        gs=0;
        flag[1]=0;
        for (int i=1;i<=zs[0];i++)
        {
            if (n%zs[i]==0)
            {
                gs++;
                p[gs]=1;    
                if (zs[i]==2)
                {   
                    flag[1]=1;
                }
            }
            while (n%zs[i]==0)
            {
                p[gs]=p[gs]*zs[i];
                n=n/zs[i];
            }
            if (zs[i]>n)
            {
                break;
            }
        }
        if (n>1)
        {
            gs++;
            p[gs]=n;    
        }
        ans=20000000000000000;
        for (int i=1;i<=mi[gs]-1;i++)
        {
            long long j=i;
            memset(m,0,sizeof(m));
            memset(c,0,sizeof(c));
            int k=1;
            while (j>0)
            {
                if (flag[k]==1)
                {
                    m[k]=p[k]*2;
                }
                else m[k]=p[k];
                if (j%2==1)
                {
                    c[k]=m[k]-1;
                }
                else c[k]=0;
                k++;j=j/2;
            }
            for (int j=k;j<=gs;j++)
            {
                if (flag[j]==1)
                {
                    m[j]=p[j]*2;
                }
                else m[j]=p[j];
                c[j]=0;
            }
            bzz=true;
            for (R long long j=2;j<=gs;j++)
            {
                R long long m1(m[j-1]),m2(m[j])
                ,c1(c[j-1]),c2(c[j])
                ,T(gcd(m1,m2))
                ,mo(m2/T);
                if ((c2-c1)%T!=0) 
                {
                    bzz=false;break;
                }
                m[j]=(m1*m2)/T;
                R long long op(ny(m1/T,mo)),oq(c2-c1),kk(ny(T,mo));
                if (op>1000000000 && oq>1000000000)
                c[j]=(cheng(oq,op,mo)*kk)%mo*m1+c1;
                else
                c[j]=(oq*kk%mo*op)%mo*m1+c1;
                
                c[j]=c[j]%m[j];
                if(c[j]<0)c[j]+=m[j];
            }
            if (bzz==true)
            {
                ans=min(ans,c[gs]);
            }
        }
        printf("%lld\n",ans);
    }
}

Guess you like

Origin www.cnblogs.com/RainbowCrown/p/11516820.html