1. 程式人生 > >牛客國慶集訓派對Day1

牛客國慶集訓派對Day1

題目描述

算術是為數不多的會讓Kuon感到棘手的事情。通常她會找Haku幫忙,但是Haku已經被她派去買東西了。於是她向你尋求幫助。 給出一個關於變數x,y的不定方程ax+by=c,顯然這個方程可能有多個整數解。Kuon想知道如果有解,使得p2*x2+p1*x+q2*y2+q1*y最小的一組整數解是什麼。為了方便,你只需要輸出p2*x2+p1*x+q2*y2+q1*y的最小值。

輸入描述:

第一行三個空格隔開的整數a,b,c(0 ≤ a,b,c≤ 105)。
第二行兩個空格隔開的整數p1,p2(1 ≤ p1,p2 ≤ 105)。
第三行兩個空格隔開的整數q1,q2(1 ≤ q1,q2 ≤ 105)。

輸出描述:

如果方程無整數解,輸出“Kuon”。
如果有整數解,輸出p2*x2+p1*x+q2*y2+q1*y的最小值。

示例1

輸入

複製

2 2 1
1 1
1 1

輸出

複製

Kuon

示例2

輸入

複製

1 2 3
1 1
1 1

輸出

複製

4

思路:擴歐+換元

程式碼如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#include<set>
#include<string>
#include<cstring>
#define ll long long
using namespace std;
ll a,b,c,p1,p2,q1,q2;
ll extgcd(ll a,ll b,ll &x,ll &y){
    ll d=a;
    if(b!=0){
        d=extgcd(b,a%b,y,x);
        y-=(a/b)*x;
    }
    else {
        x=1;
        y=0;
    }
    return d;
}
ll f(ll x,ll y){
    return p2*x*x+p1*x+q2*y*y+q1*y;
}
int main(){
    scanf("%lld%lld%lld%lld%lld%lld%lld",&a,&b,&c,&p1,&p2,&q1,&q2);
    ll x1,x0,y1,y0;
    ll gcd=extgcd(a,b,x1,y1);
    if(c%gcd||!gcd){
        printf("Kuon\n");
        return 0;
    }
    ll ans;
    if(a&&!(c%a)&&!b)ans=f(c/a,0);
    else if(!a&&(b&&!(c%b)))ans=f(0,c/b);
    else{
         double A=q2+p2*b*b/(double)(a*a);
         double B=(double)q1-(p1*b*a+2*b*c*p2)/(double)(a*a);
         double C=(p2*c*c+p1*c*a)/(double)(a*a);
         double K=-B/(double)(2*A);
         y0=y1*c/gcd;
         ll ky=-a/gcd;
         int t=(K-y0)/(double)ky;
         ll y=y0+ky*t;
         ans=f((c-b*y)/a,y);
         for(int i=-3;i<=3;i++){
            y=y0+ky*(t+i);
            ans=min(ans,f((c-b*y)/a,y));
         }
    }
    printf("%lld\n",ans);
}