式SGU - 106

トピックリンク:https://codeforces.com/problemsets/acmsguru/problem/99999/106

この問題は、トピックに関する特に良いEXGCDです。効果タイトル:+ C = 0、入力A、B、CおよびL1の範囲によって方程式AX +のソリューションの整数の方程式、R1および範囲b、L2、R2、出力満たします。

ソリューション:

  + C = 0によってAX +。この式は、最初の特別な事情を考慮してください。

1、= 0 && B = 0、C = 0、xおよびyは任意満たしている、(R1-L1 + 1)*(R2-L2 + 1)への答えそう

2、= 0 && B = 0、直接出力0

3、= 0は、式が= -c、cは複数bが直接その後、出力0でないか否かを判断することによって変換されます。(L2、R2)が、答えは同様に(R1-L1 + 1)b = 0である場合、次に、Yの範囲内で決定されます。

4、AX + = -cによる。aとbが0よりも大きいようにしよう。<0の場合、それは同様の範囲で正、その後、変更、おそらく同じ程度Bとなります。Cは上に移動し、より大きく確保しようとするまたは0 -C等しいです

図5は、AX +によって= C、exgcdで解決しました。まず、cはGCDの倍数(a、b)は、無解決策ではない場合。それ以外の場合は、式A1X + B1Y = C1を変換します。A1 = A / GCD(a、b)は、B、Cの共感。XがX0 + KBにexgcdソリューションソリューションセットセットによって決定することができ、Yは、Y0-KAです。次に、kの範囲に従って範囲を求めます。

範囲を評価すると6、我々は2つの関数の床や切り上げを使用します。床が最大(以下4.9以上の最大の整数)を切り上げ整数を表し、CEILは4.9--4場合4が3.1より大きい---丸いダウン、3.1です。その後下限、上限小さなを取ることは大きな取ることができます。

コード:

#include <iostreamの> 
する#include <cstdioを> 
する#include <cmath> 
の#include <アルゴリズム>
 使用して 名前空間をSTD。
typedefの長い 長いLL。
LL GCD(-1,11,11- B){ 
    戻り B == 0:GCD(B、%のB)。
} 
LL exgcd(-1,11,11- B、LL&X、LL&Y){
     もし、(B == 0 ){ 
        X = 1、Y = 0 返します
    } 
    LL D = exgcd(B、%のB、Y、X)。
    Y - = A / B *バツ;
    リターンD; 
} 
int型のmain()
{ 
    LL、B、C。
    CIN >> B >> C。
    C = - C。
    LL L1、R1、L2、R2; 
    CIN >> L1 >> R1 >> L2 >> R2。
    もし(C < 0 ){ 
        C = -c。A = -a; B = - B。
    } 
    であれば(< 0 ){ 
        A = -a。L1 = -L1。R1 = - R1。スワップ(L1、R1)。
    } 
    もし、(B < 0 ){ 
        B = -b。R2 = -R2。L2 = - L2; スワップ(R2、L2)。 
    } 
    もし(== 0 && B == 0 && C == 0 ){ 
        COUT <<(R1 - L1 + 1)*(R2 - L2 + 1)<< ENDL。
        リターン 0 ; 
    } 
    そう であれば(== 0 && B == 0){COUT << 0 << ENDL。リターン 0 ; }
     そう であれば(B == 0 ){
         場合(Cの%Bの== 0 &&(-c)/ B <= R2 &&(-c)/ B> = L2)COUT << R1 - L1 + 1 << ENDL ;
        coutの<< 0 << てendl;
        リターン 0 ; 
    } 
    そう であれば(== 0 ){
         場合(C%A == 0 &&(-c)/ <= R1 &&(-c)/ A> = L1)COUT << R2 - L2 + 1 << ENDL ;
        他の coutの<< 0 << てendl;
        リターン 0 ; 
    } 
    LL D = GCD(A、B)。
    もし(C%dを=!0)プット(" 0 " );
    { 
        LL X、Y。
//        C = -c。
        / = D; B / A = D; C / = D。
        exgcd(A、B、X、Y)。
        X = X * C; Y = Y * C。
//         COUT << << " - " << B << "==" << C << " - " << D << "===" << X << " - " < <Y << ENDL。
        ダブルRR1、LL1、RR2、LL2。
        RR1 = 二重(R1)、LL1 = 二重(L1)。
        RR2 = 二重(R2); LL2 = 二重(L2)。
        LL UPX =フロア((RR1-X)/ B)、downx = CEIL((LL1-X)/ B)。
        LL upy =フロア((Y-LL2)/)、べ= CEIL((Y-RR2)/ )。 <<(ANS < 00:ANS)<< てendl; 
    } 
    戻り 0 
}

補足Exgcd(INT、INT B、INT&X、INT&Y)知識:

証明:= GCD(a、b)はKによってAX +。まず= GCD(b)でAX +を計算し、解決した後、Kにすることができます。

        BX +(%b)はY = GCD(B、%のB)。

   = A-B%(a / b)が(整数除算を除く)* B

 Y = X-(オープン= GCDによってBX + ay-(/ B)*(B、%のB)= GCD(A、B)= AX +によって、及び、対応する同等の、X = Y、入りますA / B)* B * Y

X0 + KB、Y:Y0-KA解集合は、決定されたxと

exgcdコード:

void exgcd(int a,int b,int &x,int &y){
    if(b==0) {x=1,y=0}
    else {
        exgcd(a,b,x,y);
        int t=x;
        x=y;y=t-a/b*y;
    }
}

Exgcd还可以用来求解逆元。证明过程用到了同余方程即ax%b=c,也可记为ax=c(modb)当c等与1时,x就是a的逆元。

求解过程:ax-b*y=1,带入exgcd中,x就是a的逆元。

 

おすすめ

転載: www.cnblogs.com/Accepting/p/12581918.html