题型:数论
题意:求解不定方程ax+by=c,要求x+y最小且x、y非负,如果多个x+y,x尽量小。
分析:
扩展欧几里得求解方程,注意格式问题。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#define LL long long
using namespace std;
/**
不定方程的求解思路:
扩展gcd求出ax+by=gcd(a,b)=d的一组特解(x0,y0)
如果c%d!=0,无解
a0 = a/d
b0 = b/d
x0 = x0*(c/d)
y0 = y0*(c/d)
通解:
x=x0+k*b0
y=y0-k*a0
如果要求|x|+|y|最小,有-b0<y<b0
*/
/**求解ax+by=c,x为非负数的最小解,且如果x和y非负,x+y最小*/
class IndefiniteEquation {
typedef LL DataType;
DataType a,b,c;
DataType x,y;
/**gcd*/
DataType gcd(DataType A,DataType B) {
return B?gcd(B,A%B):A;
}
/**扩展gcd*/
DataType ext_gcd(DataType A,DataType B,DataType &x0,DataType &y0) {
DataType t,ret;
if(!B) {
x = 1;
y = 0;
return A;
}
ret = ext_gcd(B,A%B,x0,y0);
t = x0;
x0 = y0;
y0 = t-A/B*y0;
return ret;
}
public:
void init(DataType aa,DataType bb,DataType cc) {
a = aa;
b = bb;
c = cc;
}
/**false无解,true有解*/
bool solve() {
if(c==0) {
x = y = 0;
return true;
}
if(a==0 && b==0) {
return false;
}
if(a==0) {
if(c%b) {
return false;
} else {
x = 0;
y = c/b;
return true;
}
}
if(b==0) {
if(c%a) {
return false;
} else {
x = c/a;
y = 0;
return true;
}
}
DataType d = gcd(a,b);
if(c%d) return false;
a /= d;
b /= d;
c /= d;
d = ext_gcd(a,b,x,y);
DataType t = c%b;
x %= b;
x = (x*t)%b;
x = (x+b)%b;
y = (c-(x*a))/b;
return true;
}
/**解x*/
DataType x0(){
return x;
}
/**解y*/
DataType y0(){
return y;
}
}ts;
void no(){
puts("Unquibable!");
}
void out(LL x,LL y){
printf("%lld foom",x);
if(x!=1) printf("s");
printf(" and %lld foob",y);
if(y!=1) printf("s");
puts(" for a twob!");
}
int main() {
LL a,b,c;
while(~scanf("%lld%lld%lld",&a,&b,&c)){
if(!(a|b|c)) break;
ts.init(a,b,c);
bool flag = ts.solve();
if(flag){
if(ts.y0()<0) no();
else{
out(ts.x0(),ts.y0());
}
}
else{
no();
}
}
return 0;
}