sgu248:Integer Linear Programming(扩展欧几里得)

来源:互联网 发布:明解c语言入门篇pdf 编辑:程序博客网 时间:2024/05/17 06:52

题目大意:
      给定正整数序列Cn和一个正整数V,求出一组非负整数解Xn使得CiXi=VXi最小,无解输出1

分析:
      对于n=1的情况不说了。
      对于n=2的情况我们扩展欧几里得一下,然后调整成和为最小的。
      对于n=3的情况,我们枚举一个X,其余两个Xn=2的方法做。

AC code:

#include <cstdio>#include <algorithm>#include <iostream>typedef long long LL;using namespace std;const LL INF = 1LL<<60;namespace math{    LL gcd(LL a, LL b)    {        while(b) b^=a^=b^=a%=b;        return a;    }    LL ext_gcd(LL a, LL b, LL &x, LL &y)    {        if(!b)        {            x = 1, y = 0;            return a;        }        LL ret = ext_gcd(b, a%b, x, y);        LL tmp = x;        x = y, y = tmp-a/b*y;        return ret;    }    bool adjust(LL a, LL b, LL &x, LL &y)    {        LL g = gcd(a, b);        LL kx = b/g, ky = a/g;        if(x < 0)        {            y -= ((-x-1)/kx+1)*ky;            x += ((-x-1)/kx+1)*kx;        }        if(y < 0)        {            x -= ((-y-1)/ky+1)*kx;            y += ((-y-1)/ky+1)*ky;          }        if(x < 0 || y < 0) return false;        if(kx < ky)        {            x += y/ky*kx;            y -= y/ky*ky;           }        else if(kx > ky)        {            y += x/kx*ky;            x -= x/kx*kx;           }        return true;    }}bool solve(LL a, LL b, LL &x, LL &y, LL v){    LL ret, gcd = math::gcd(a, b);    if(v%gcd != 0) return false;    math::ext_gcd(a, b, x, y);    x *= v/gcd, y *= v/gcd;    return math::adjust(a, b, x, y);}int main(){    #ifndef ONLINE_JUDGE    freopen("input.txt", "r", stdin);    freopen("output.txt", "w", stdout);    #endif    LL n, a[5] = {0}, v;    cin >> n;    for(int i = 1; i <= n; ++i)        cin >> a[i];    cin >> v;    LL ans = 0;    LL x, y;    if(n == 1)    {        if(v%a[1] == 0) ans = v/a[1];        else ans = -1;      }    else if(n == 2)    {        if(solve(a[1], a[2], x, y, v)) ans = x+y;        else ans = -1;    }    else    {        ans = INF;        for(int i = v/a[3]; i >= 0; --i)            if(solve(a[1], a[2], x, y, v-i*a[3]))                ans = min(ans, x+y+i);        if(ans == INF) ans = -1;    }    cout << ans << endl;    #ifndef ONLINE_JUDGE    fclose(stdin);    fclose(stdout);    #endif    return 0;}
0 0
原创粉丝点击