牛客国庆集训派对Day1 C Utawarerumono(暴力)

版权声明:本文为博主原创文章,未经博主允许不得转载。 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);
 
}

猜你喜欢

转载自blog.csdn.net/qq_37025443/article/details/82930498