[ZLXOI2015]殉国

2057. [ZLXOI2015]殉国

http://cogs.pro/cogs/problem/problem.php?pid=2057

★☆   输入文件: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<=103,b<=103,c<=103

对于20%的数据,a<=104,b<=104,c<=106

对于50%的数据,a<=109b<=109,c<=109

对于100%数据,a<=31018b<=31018,c<=31018

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

首先通过扩展欧几里得求出任意一组解x,y

令g=gcd(a,b) ,a/=g,b/=g

那么 任意解都可以表示成 x-k*b,y+k*a  ,k∈Z

那么 本题 第二问就是问在满足 x-k*b>0,y+k*a>0 的情况下,k的个数

移项得, -y/a < k < x/b

所以解的个数为  floor(x/b)-ceil(-y/a)+1

看第一问

当k增加1,x+y就变成了 x+y+(a-b)

当k加1,x+y 就增加a-b

当k减1,x+y就减少a-b

所以 x+y的最大和最小一定是 k的取值范围的边界

注意用long double 

#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
void read(LL &x)
{
    x=0; char c=getchar();
    while(c<'0' || c>'9') c=getchar();
    while(c>='0' && c<='9') { x=x*10+c-'0'; c=getchar(); }
}
void exgcd(LL a,LL b,LL &g,LL &x0,LL &y0)
{
    if(!b) { g=a; x0=1; y0=0; }
    else { exgcd(b,a%b,g,y0,x0); y0-=x0*(a/b); }
}
int main()
{
    freopen("BlackHawk.in","r",stdin);
    freopen("BlackHawk.out","w",stdout);
    LL a,b,c;
    LL g,x0,y0,x,y;
    read(a); read(b); read(c);
    exgcd(a,b,g,x0,y0);
    if(c%g) { printf("-1 -1
0"); return 0; }
    a/=g; 
    b/=g; 
    x=x0*c/g;  
    y=y0*c/g; 
    LL s=floor((long double)x/b);
    LL t=ceil((long double)-y/a);
    if(s-t<0) { printf("-1 -1
0"); return 0; }
    LL ans1=x+y+(a-b)*s;
    LL ans2=x+y+(a-b)*t;
    printf("%lld %lld
%lld",min(ans1,ans2),max(ans1,ans2),s-t+1);
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7325506.html