zoukankan      html  css  js  c++  java
  • 扩展欧几里德算法 cogs.tk 2057. [ZLXOI2015]殉国

    2057. [ZLXOI2015]殉国

    ★☆   输入文件:BlackHawk.in   输出文件:BlackHawk.out   评测插件
    时间限制:0.05 s   内存限制:256 MB

    【题目描述】

    正义的萌军瞄准了位于南极洲的心灵控制器,为此我们打算用空袭摧毁心灵控制器,然而心灵控制器是如此强大,甚至能缓慢控制飞行员。一群勇敢的士(feng)兵(zi)决定投弹后自杀来避免心灵控制。然而自杀非常痛苦,所以萌军指挥官决定到达目的地后让飞机没油而坠落(也避免逃兵)。军官提供两种油:石油和中国输送来的地沟油,刚开始飞机没有油,飞机可以加几桶石油和几桶地沟油(假设石油和地沟油都有无限桶),飞机落地时必须把油耗尽,已知一桶石油和一桶地沟油所能支撑的飞行距离分别为a,b,驾驶员们必须飞往一个目的地,总距离为c.

    1.最少,最多需要加几桶油,若只有一种方案,最少和最多的是相同的.

    2.总共有多少种不同的加油配方(死法)能到达目的地。

    【输入格式】

    只有一行,三个正整数a,b,c

    【输出格式】

    两行,第一行为最少加几次油和最多加几次油,

    第二行为加油方法总数。

    若不存在任何方法,第一行输出-1 -1

    第二行输出0

    【样例输入】

    样例1:
    2 3 10
    样例2:
    6 8 10
    

    【样例输出】

    样例1:
    4 5
    2
    样例2:
    -1 -1
    0
    

    【提示】

    样例解释:

    样例一:飞机加两次石油,两次地沟油,总次数为4,2*2+3*3=10

    飞机加五次石油,不加地沟油,总次数为5,2*5+3*0=10

    总共两种

    样例二:飞机无法到达目的地

    数据范围:

    对于10%的数据,$a<=10^3,b<=10^3,c<=10^3$

    对于20%的数据,$a<=10^4,b<=10^4,c<=10^6$

    对于50%的数据,$a<=10^9,b<=10^9,c<=10^9$

    对于100%数据,$a<=3·10^{18},b<=3·10^{18},c<=3·10^{18}$

    三个答案分值权重分别为20%,30%,50% 

     1 /*
     2 65分代码:寻找方法数和最大值和最小值,都是用的暴力,实在没想出其他的方法。
     3 */
     4 #include<iostream>
     5 using namespace std;
     6 #include<cstdio>
     7 typedef long long ll;
     8 void exgcd(ll a,ll b,ll &x,ll &y,ll &gcd)
     9 {
    10     if(!b)
    11     {
    12         gcd=a;x=1;y=0;
    13         return ;
    14     }
    15     exgcd(b,a%b,x,y,gcd);
    16     ll t=x;
    17     x=y;
    18     y=t-(a/b)*y;
    19 }
    20 int main()
    21 {
    22     freopen("BlackHawk.in","r",stdin);
    23     freopen("BlackHawk.out","w",stdout);
    24     ll a,b,c,x,y,gcd,ans,minn,maxx;
    25     cin>>a>>b>>c;
    26     exgcd(a,b,x,y,gcd);
    27     if(c%gcd)
    28     {
    29         minn=maxx=-1;
    30         ans=0;
    31     }
    32     else
    33     {
    34         ll a0=a/gcd,b0=b/gcd;
    35         ll k=c/gcd;
    36         x*=k;y*=k;
    37         ans=0;
    38         if(x<0)
    39         {
    40             ll x1=-x;
    41             x1/=b0;
    42             x+=x1*b0;
    43             y-=x1*a0;
    44             if(x<0) x+=b0,y-=a0;
    45         }
    46         if(y<0)
    47         {
    48             ll y1=-y;
    49             y1/=a0;
    50             y+=y1*a0;
    51             x-=y1*b0;
    52             if(y<0) y+=a0,x-=b0;
    53         }
    54          minn=maxx=x+y;
    55         ll x2=x,y2=y;
    56         for(;y2>=0&&x2>=0&&x2<=c&&y2<=c;++ans)
    57         {
    58             minn=min(minn,x2+y2);
    59             maxx=max(maxx,x2+y2);
    60             x2+=b0;
    61             y2-=a0;
    62         }
    63         for(;y>=0&&x>=0&&x<=c&&y<=c;++ans)
    64         {
    65             minn=min(minn,x+y);
    66             maxx=max(maxx,x+y);
    67             x-=b0;y+=a0;
    68         }
    69         --ans;
    70     }
    71     if(ans==0) minn=maxx=-1;//
    72     cout<<minn<<" "<<maxx<<endl<<ans;
    73     fclose(stdin);
    74     fclose(stdout);
    75     return 0;
    76 }

    网上的AC代码:

    求exgcd,由xx=x*c/d+b/d*t0,yy=y*c/da/d*t0
    得到t的区间[l,r]
    方法数=r-l+1;
    因为方程线性,所以最值在l、r取到
    要写long double!!

     1 #include<cstdio>
     2 #include<cmath>
     3 #define min(x,y) x<y?x:y
     4 #define max(x,y) x>y?x:y
     5 using namespace std;
     6 long long a,b,c,d,x,y,xx,yy,ans1,ans2,ans;
     7 void exgcd(long long a,long long b,long long &d,long long &x,long long &y)
     8 {
     9     if(!b)  d=a,x=1,y=0;
    10     else exgcd(b,a%b,d,y,x),y-=x*(a/b);
    11 }
    12 int main()
    13 {
    14     freopen("BlackHawk.in","r",stdin);
    15     freopen("BlackHawk.out","w",stdout);
    16     scanf("%lld%lld%lld",&a,&b,&c);
    17     exgcd(a,b,d,x,y);
    18     if(!(c%d))
    19     {
    20         xx=ceil((long double)-x/b*c);
    21         yy=floor((long double)y/a*c);
    22         ans=yy-xx+1;
    23         ans1=x*c/d+y*c/d+(b-a)/d*yy;
    24         ans2=x*c/d+y*c/d+(b-a)/d*xx;
    25     }
    26     if(ans<=0) printf("-1 -1
    0");
    27     else printf("%lld %lld
    %lld",min(ans1,ans2),max(ans1,ans2),ans);
    28 }
  • 相关阅读:
    GNU make manual 翻译(九十九)
    GNU make manual 翻译( 九十五)
    Shell的 for 循环小例子
    makefile中对目录遍历的小例子
    GNU make manual 翻译(九十三)
    GNU make manual 翻译( 一百)
    GNU make manual 翻译( 九十七)
    GNU make manual 翻译( 九十八)
    mapserver4.8.3 的readme.win32的中文翻译文件
    遥控器编程
  • 原文地址:https://www.cnblogs.com/c1299401227/p/5954578.html
Copyright © 2011-2022 走看看