版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37025443/article/details/82930498
题意:
关于变量x,y的不定方程ax+by=c,显然这个方程可能有多个整数解。Kuon想知道如果有解,使得p2*x2+p1*x+q2*y2+q1*y最小的一组整数解是什么。为了方便,你只需要输出p2*x2+p1*x+q2*y2+q1*y的最小值。
如果方程无整数解,输出“Kuon”。如果有整数解,输出p2*x2+p1*x+q2*y2+q1*y的最小值。
解析:
这道题我真的不想说什么.....数据水的要死,但是卡了我一天...
最后发现是ll 转换成 double 运算然后再转回 ll 出现了问题.....
我的思路就是把y用x代替,然后变成一个一元二次方程,然后按照x=-a/2b,求最值就可以了
官方题解使用暴力取枚举x,然后分别带入原来的式子求最值的,但暴力的范围是[-1e5,1e5]这个我搞不懂怎么来的,
可能按照数据大小猜的把...
最后就是这道题,a=0&b=0&c=0,a&!b,!a&b的数据都没有,我看过的代码,这里的特判输出什么的都有..
按我的理解a=0的话,那么x的范围就是[-INF,INF],并且不受y影响,那么就直接取p2*x2+p1*x的最小值就可以了,b=0同理
暴力枚举的方法
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e5+10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll s1,s2,s3;
ll gcd(ll a,ll b)
{
ll tmp;
while(b)
{
tmp=a%b;
a=b;
b=tmp;
}
return a;
}
ll a,b,c,yu;
ll p1,p2,q1,q2;
inline ll cal(ll x)
{
ll y=(c-a*x)/b;
return p2*x*x+p1*x+q2*y*y+q1*y;
}
inline ll calzz(ll p,ll q,ll x)
{
return p*x*x+q*x;
}
inline ll solvezz(ll p2,ll p1)
{
ll ne;
ll ans1=INF;
ne=-p1/(2*p2);
ans1=min(ans1,calzz(p2,p1,ne-1));
ans1=min(ans1,calzz(p2,p1,ne));
ans1=min(ans1,calzz(p2,p1,ne+1));
ans1=min(ans1,calzz(p2,p1,ne+2));
return ans1;
}
int main()
{
scanf("%lld%lld%lld",&a,&b,&c);
scanf("%lld%lld",&p1,&p2);
scanf("%lld%lld",&q1,&q2);
if(a==0&&b==0)
{
if(c)
printf("Kuon\n");
else
{
printf("%lld\n",solvezz(p2,p1)+solvezz(q2,q1));
}
return 0;
}
ll g=gcd(a,b);
if(c%g!=0)
{
printf("Kuon\n");
return 0;
}
a=a/g;
b=b/g;
c=c/g;
ll ans;
if(b==0)
{
ll x=c/a;
ans=p2*x*x+p1*x+solvezz(q2,q1);
printf("%lld\n",ans);
return 0;
}
if(a==0)
{
ll x=c/b;
ans=q2*x*x+q1*x+solvezz(p2,p1);
printf("%lld\n",ans);
return 0;
}
ans=INF;
for(ll i=-100000;i<=100000;i++)
{
if((c-a*i)%b==0)
{
ans=min(ans,cal(i));
}
}
printf("%lld\n",ans);
}
二元一次方程求解
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e5+10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll s1,s2,s3;
ll gcd(ll a,ll b)
{
ll tmp;
while(b)
{
tmp=a%b;
a=b;
b=tmp;
}
return a;
}
ll a,b,c,yu;
ll p1,p2,q1,q2;
inline ll cal(ll x)
{
ll y=(c-a*x)/b;
return p2*x*x+p1*x+q2*y*y+q1*y;
}
inline ll solve(ll stx)
{
ll ans=INF;
ll w=(stx%b+b)%b;
//ll mm=findstx(stx);
ll mm=stx+(yu-w);
ans=min(ans,cal(mm));
ans=min(ans,cal(mm-b));
ans=min(ans,cal(mm-b-b));
ans=min(ans,cal(mm-b-b-b));
ans=min(ans,cal(mm+b));
ans=min(ans,cal(mm+b+b));
ans=min(ans,cal(mm+b+b+b));
return ans;
}
inline void findyu()
{
for(ll i=0;i<b;i++)
{
if(((c-a*i)%b+b)%b==0)
{
yu=i;
return;
}
}
}
inline ll calzz(ll p,ll q,ll x)
{
return p*x*x+q*x;
}
inline ll solvezz(ll p2,ll p1)
{
ll ne;
ll ans1=INF;
ne=-p1/(2*p2);
ans1=min(ans1,calzz(p2,p1,ne-1));
ans1=min(ans1,calzz(p2,p1,ne));
ans1=min(ans1,calzz(p2,p1,ne+1));
ans1=min(ans1,calzz(p2,p1,ne+2));
return ans1;
}
int main()
{
scanf("%lld%lld%lld",&a,&b,&c);
scanf("%lld%lld",&p1,&p2);
scanf("%lld%lld",&q1,&q2);
if(a==0&&b==0)
{
if(c)
printf("Kuon\n");
else
{
printf("%lld\n",solvezz(p2,p1)+solvezz(q2,q1));
//printf("0\n");
}
return 0;
}
ll g=gcd(a,b);
if(c%g!=0)
{
printf("Kuon\n");
return 0;
}
a=a/g;
b=b/g;
c=c/g;
ll ans;
if(b==0)
{
ll x=c/a;
ans=p2*x*x+p1*x+solvezz(q2,q1);
printf("%lld\n",ans);
return 0;
}
if(a==0)
{
ll x=c/b;
ans=q2*x*x+q1*x+solvezz(p2,p1);
printf("%lld\n",ans);
return 0;
}
s1=p2*b*b+q2*a*a;
s2=p1*b*b-2*a*c*q2-q1*a*b;
s3=q2*c*c+q1*c*b;
ll stx=-s2/(2*s1);
/*yu=b-c%b;
if(abs(c-a*yu)%b!=0)
{
yu=c%b;
}*/
findyu();
ans=solve(stx);
ans=min(ans,solve(stx+1));
ans=min(ans,solve(stx-1));
printf("%lld\n",ans);
}