• luogu2833 等式


    题目大意

    给出(a,b,c,x_1,x_2,y_1,y_2),求满足(ax+by+c=0),且(xin[x1,x2],yin [y1,y2])的整数解有多少对。

    题解

    用扩展欧几里得算法算出方程(ax+by=-c)的一个解,再将该解移动到题目所要求的范围内。具体操作看代码。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define ll long long
    #define NoAns {printf("0
    ");return 0;}
    
    ll Exgcd(ll a, ll b, ll &x, ll &y)
    {
    	if (b == 0)
    	{
    		x = 1;
    		y = 0;
    		return a;
    	}
    	ll d = Exgcd(b, a % b, x, y);
    	ll tx = x;
    	x = y;
    	y = tx - y * (a / b);
    	return d;
    }
    
    ll Gcd(ll a, ll b)
    {
    	return b ? Gcd(b, a%b) : a;
    }
    
    bool Solve(ll a, ll b, ll c, ll &x, ll &y, ll &deltaX, ll &deltaY)
    {
    	int gcd = Gcd(a, b);
    	if (c%gcd != 0)
    		return false;
    	Exgcd(a, b, x, y);//易忘点:好好下定义,传入的参数不是a%gcd,b%gcd
    	x *= c / gcd;
    	y *= c / gcd;
    	deltaX = b / gcd;
    	deltaY = -a / gcd;//易忘点:负号
    	return true;
    }
    
    ll MoveToRange(ll orgP, ll delta, ll l, ll r, ll toP, bool &moveFailed)
    {
    	ll k = (toP - orgP) / delta;
    	int higherP = delta > 0 ? 1 : -1;
    	if (orgP + k * delta > r)
    		k-=higherP;//注意此处不能直接--,因为delta<0时k越小k*delta越大
    	else if (orgP + k * delta < l)
    		k+=higherP;
    	if (orgP + k * delta > r || orgP + k * delta < l)
    		moveFailed = true;
    	return k;
    }
    
    int main()
    {
    	ll a, b, c, x1, x2, y1, y2;
    	scanf("%lld%lld%lld%lld%lld%lld%lld", &a, &b, &c, &x1, &x2, &y1, &y2);
    
    	if (x2 < x1 || y2 < y1)
    		NoAns
    
    	if (a == 0 && b == 0)
    	{
    		if (c == 0)
    			printf("%lld
    ", (x2 - x1 + 1) * (y2 - y1 + 1));
    		else
    			NoAns
    		return 0;
    	}
    
    	if (a == 0)
    	{
    		if (c%b == 0 && y1 <= -c / b && -c / b <= y2)
    			printf("%lld
    ", x2 - x1 + 1);
    		else
    			NoAns
    		return 0;
    	}
    
    	if (b == 0)
    	{
    		if (c%a == 0 && x1 <= -c / a && -c / a <= x2)
    			printf("%lld
    ", y2 - y1 + 1);
    		else
    			NoAns
    		return 0;
    	}
    
    	ll x, y, deltaX, deltaY;
    	if (!Solve(a, b, -c, x, y, deltaX, deltaY))
    		NoAns
    
    	bool moveFailed = false;
    	ll kx1 = MoveToRange(x, deltaX, x1, x2, x1, moveFailed);
    	ll kx2 = MoveToRange(x, deltaX, x1, x2, x2, moveFailed);
    	ll ky1 = MoveToRange(y, deltaY, y1, y2, y1, moveFailed);
    	ll ky2 = MoveToRange(y, deltaY, y1, y2, y2, moveFailed);
    	if (moveFailed)
    		NoAns
    
    	if (kx1 > kx2)
    		swap(kx1, kx2);
    	if (ky1 > ky2)
    		swap(ky1, ky2);
    	ll kLow = max(kx1, ky1), kHigh = min(kx2, ky2);
    	if (kLow > kHigh)
    		NoAns
    
    	printf("%lld
    ", kHigh - kLow + 1);
    	return 0;
    }
    
  • 相关阅读:
    数据结构之查找算法总结笔记
    html的a链接的href怎样才另起一个页面
    深入理解CSS中的空白符和换行
    CSS文本方向
    alert()与console.log()的区别
    CSS旧版flex及兼容
    Java:类与继承
    Java中只有按值传递,没有按引用传递!
    String作为方法参数传递 与 引用传递
    Java:按值传递还是按引用传递详细解说
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9000407.html
Copyright © 2020-2023  润新知