[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<=109,b<=109,c<=109
对于100%数据,a<=3⋅1018,b<=3⋅1018,c<=3⋅1018
三个答案分值权重分别为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\n0"); 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\n0"); return 0; } LL ans1=x+y+(a-b)*s; LL ans2=x+y+(a-b)*t; printf("%lld %lld\n%lld",min(ans1,ans2),max(ans1,ans2),s-t+1); }