/**
** 题意: 求x,y 满足 x*pa+y*pb=n 同时使得 p = x*ca+y*cb的值最小,若有多种可能,则选择最大x值的组合
** 分析: x*pa+y*pb=n 可以用 线性同余方程 求得各组解: X=x+(pb/q)*t, Y=y-(pa/q)*t
** t为整数,显然 X,Y>=0,所以 -x/(pb/q) <= t <= y/(pa/q)
** 欲使 x*ca+y*cb 最小, 注意到 其中 [(pb/q)*t]*ca + [-(pa/q)*t]*cb = (pb*ca-pa*cb)/q*t
** 当pb*ca-pa*cb<0,t应取最大值;
** 当pb*ca-pa*cb>0,t应取最小值;
** 当pb*ca-pa*cb=0,应选择较大的X值,显然 pb/q总是大于0的,所以t 选择最大值,X取得更大值
** http://zh.wikipedia.org/wiki/%E6%89%A9%E5%B1%95%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97%E7%AE%97%E6%B3%95
***/
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 5 /** 6 ** 扩展欧几里德算法(辗转相除法), x*a+y*b=gcd(a,b)=q 7 **/ 8 long long x,y,q; 9 void extend_eulid(long long a,long long b){ 10 if(b==0){ 11 x=1; 12 y=0; 13 q=a; 14 } 15 else{ 16 extend_eulid(b,a%b); 17 //收集辗转相除法中产生的式子,倒回去,可以得到ax+by=gcd(a,b)的整数解 18 long long temp=x; 19 x = y; 20 y = temp-a/b*y; 21 } 22 } 23 int main() 24 { 25 int n,ca,pa,cb,pb,cnt=1; 26 long long upper,lower,t; 27 while(cin>>n&&n){ 28 cin>>ca>>pa>>cb>>pb; 29 extend_eulid(pa,pb); 30 if(n%q!=0) 31 cout<<"Data set "<<cnt++<<": cannot be flown"<<endl; 32 else{ 33 //求特解 34 x = x*n/q; 35 y = y*n/q; 36 upper = (long long)floor((double)y/(pa/q)); //返回小于或者等于指定表达式的最大整数头 37 lower = (long long)ceil((double)-x/(pb/q)); //返回大于或者等于指定表达式的最小整数头 38 t = pb*ca-pa*cb<=0 ? upper : lower; 39 cout<< "Data set "<<cnt++<<": "<<x+(pb/q)*t<<" aircraft A, "<<y-(pa/q)*t<<" aircraft B"<<endl; 40 } 41 } 42 return 0; 43 }