1. 程式人生 > >牛客國慶集訓派對Day1 C Utawarerumono(暴力)

牛客國慶集訓派對Day1 C Utawarerumono(暴力)

題目連結

題意:

關於變數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);
 
}