1. 程式人生 > >歐幾里得及拓展歐幾里得

歐幾里得及拓展歐幾里得

歐幾里得

int gcd(int a,int b){

    return (b==0)?a:gcd(b,a%b);    //一條語句搞定(三元運算子)裝逼,跟上面略有不同,上面做到t=0,這裡做到b=0

}

拓展歐幾里得

int gcd(int a,int b){

    return (b==0)?a:gcd(b,a%b);    //一條語句搞定(三元運算子)裝逼,跟上面略有不同,上面做到t=0,這裡做到b=0

}

ll lcm(ll a, ll b) {
    return a / gcd(a,b) * b;
}
int exgcd(int a,int b,int &x,int &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    int r=exgcd(b,a%b,x,y);
    int t=x;
    x=y;
    y=t-a/b*y;
    return r;
}

拓展歐幾里得求整數解個數

ll gcd(ll a, ll b) {
	return b ? gcd(b, a%b) : a;
}

ll lcm(ll a, ll b) {
	return a / gcd(a, b) * b;
}

ll extend_gcd(ll a, ll b, ll&x, ll&y) {
	if (!b) {
		x = 1;
		y = 0;
		return a;
	}
	ll xt = 0, yt = 0;
	ll d = extend_gcd(b, a % b, xt, yt);
	x = yt;
	y = xt - yt * (a / b);
	return d;
}

ll cal(ll a, ll b, ll n) {    //計算ax+by == n的非負整數解組數
	ll x = 0, y = 0, d;
	d = extend_gcd(a, b, x, y);
	if (n % d != 0) {
		return 0;
	}
	x *= n / d, y *= n / d;
	ll LCM = lcm(a, b);
	ll t1 = LCM / a, t2 = LCM / b;
	if (x < 1) {
		ll num = (1 - x) / t1;
		x += num * t1;
		y -= num * t2;
		if (x < 1) {
			y -= t2;
			x += t1;
		}
	}
	if (y < 1) {
		ll num = (1 - y) / t2;
		y += num * t2;
		x -= num * t1;
		if (y < 1) {
			y += t2;
			x -= t1;
		}
	}
	ll ans = x > 0 && y > 0;
	if (ans) {
		ans += min((x - 1) / t1, ((n - 1) / b - y) / t2);
		ans += min((y - 1) / t2, ((n - 1) / a - x) / t1);
	}
	return ans;
}