トピックリンク: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 < 0?0: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的逆元。