关于ax+by=c的解x,y的min(|x|+|y|)值问题

时间:2023-03-09 14:41:05
关于ax+by=c的解x,y的min(|x|+|y|)值问题

  首先我们移动一下项关于ax+by=c的解x,y的min(|x|+|y|)值问题,并强行让a>b。

  然后我们可以画出这样一个图像关于ax+by=c的解x,y的min(|x|+|y|)值问题

  我们发现,在线段l与x轴交点处的下方,x,y的绝度值是递增的,所以我们不考虑那个最小点在下端。

  之后我们发现在点的上端,因为斜率小于-1,x的减少远没有y加的快,所以我们知道极点在l与x轴的交汇处。

  但是该点不一定是整点啊。。

  所以我们只要找到它上面和下面最近的两个整点即可。

  所以我们求ax+by=c最小的正整数解y即可,之后调出x,然后y减去a,再求x,比较两次min(|x|+|y|),就可以得出答案了。

  当然如果第一次求出来的y=0,答案就是它了。。

  

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath> #define ll long long using namespace std; ll gcd(ll a,ll b)
{
return b==?a:gcd(b,a%b);
} ll x,y; void exgcd(ll n,ll m)
{
if(m==){x=,y=;return;}
exgcd(m,n%m);ll t=x;
x=y;y=t-n/m*y;
} int main()
{
ll a,b,d;
scanf("%lld%lld",&a,&b);
ll gd=gcd(a,b);
a/=gd,b/=gd;
exgcd(a,b);
while(~scanf("%lld",&d))
{
if(d%gd){printf("BeiJu!\n");continue;}
d/=gd;
ll ans1=(y*d%a+a)%a,ans;
ans=abs(ans1)+abs((d-ans1*b)/a);
if(!ans1){printf("%lld\n",ans);return ;}
ans1-=a;
ans=min(ans,abs(ans1)+abs((d-ans1*b)/a));
printf("%lld\n",ans);
}
return ;
}

  代码略丑。。题目给出a,b,给出一堆c,求min(|x|+|y|).