标签:
题意:给一个数A,有6种操作,+a,-a,+b,-b,+(a+b),-(a+b),每次选择一种,用最少的次数变成B。
思路:由于不同的操作先后顺序对最后的结果没有影响,并且加一个数与减一个相同的数不能同时有,如果有,把它们都去掉结果更优。所以不妨设+a操作进行了x次(x为负表示-a操作进行了|x|次,y同理),+b操作进行了y次,那么问题转化为ax + by = |A-B|的解,使得结果最小,其中如果x,y异号,结果为|x|+|y|,同号则为max(|x|,|y|,因为+a,+b或-a,-b可以合并)。令c=|A-B|,如果c%gcd(a,b)!=0,这个显然是没有解的,直接输出-1。否则令a=a/g,b=b/g,c=c/g,其中gcd(a,b)=1,令ax+by=1的一个解为(x0,y0),则方程的通解可以表示为(x0+kb,y0-ka),下面进行关键的一步:由于ax+bx=c可以转化为c个ax+bx=1相加,所以ax+bx=c的解可以表示为(cx0+Kb,cy0-Ka)(K取任意整数),这里a,b,c,x0,y0都是已知的,K是个变量,K确定后那么答案也就确定了,由于答案是K的单峰函数所以可以三分一下,求得最小答案。由于K的范围不确定,需要用大整数=_=(醉了)!具体看代码。
1 #pragma comment(linker, "/STACK:10240000,10240000") 2 3 #include <iostream> 4 #include <cstdio> 5 #include <algorithm> 6 #include <cstdlib> 7 #include <cstring> 8 #include <map> 9 #include <queue> 10 #include <deque> 11 #include <cmath> 12 #include <vector> 13 #include <ctime> 14 #include <cctype> 15 #include <set> 16 #include <bitset> 17 #include <functional> 18 #include <numeric> 19 #include <stdexcept> 20 #include <utility> 21 22 using namespace std; 23 24 #define mem0(a) memset(a, 0, sizeof(a)) 25 #define mem_1(a) memset(a, -1, sizeof(a)) 26 #define lson l, m, rt << 1 27 #define rson m + 1, r, rt << 1 | 1 28 #define define_m int m = (l + r) >> 1 29 #define rep_up0(a, b) for (int a = 0; a < (b); a++) 30 #define rep_up1(a, b) for (int a = 1; a <= (b); a++) 31 #define rep_down0(a, b) for (int a = b - 1; a >= 0; a--) 32 #define rep_down1(a, b) for (int a = b; a > 0; a--) 33 #define all(a) (a).begin(), (a).end() 34 #define lowbit(x) ((x) & (-(x))) 35 #define constructInt4(name, a, b, c, d) name(int a = 0, int b = 0, int c = 0, int d = 0): a(a), b(b), c(c), d(d) {} 36 #define constructInt3(name, a, b, c) name(int a = 0, int b = 0, int c = 0): a(a), b(b), c(c) {} 37 #define constructInt2(name, a, b) name(int a = 0, int b = 0): a(a), b(b) {} 38 #define pchr(a) putchar(a) 39 #define pstr(a) printf("%s", a) 40 #define sstr(a) scanf("%s", a) 41 #define sint(a) scanf("%d", &a) 42 #define sint2(a, b) scanf("%d%d", &a, &b) 43 #define sint3(a, b, c) scanf("%d%d%d", &a, &b, &c) 44 #define pint(a) printf("%d\n", a) 45 #define test_print1(a) cout << "var1 = " << a << endl 46 #define test_print2(a, b) cout << "var1 = " << a << ", var2 = " << b << endl 47 #define test_print3(a, b, c) cout << "var1 = " << a << ", var2 = " << b << ", var3 = " << c << endl 48 49 typedef long long LL; 50 typedef pair<int, int> pii; 51 typedef vector<int> vi; 52 53 const int dx[8] = {0, 0, -1, 1, 1, 1, -1, -1}; 54 const int dy[8] = {-1, 1, 0, 0, 1, -1, 1, -1 }; 55 const int maxn = 102; 56 const int md = 10007; 57 const int inf = 1e9 + 7; 58 const LL inf_L = 1e18 + 7; 59 const double pi = acos(-1.0); 60 const double eps = 1e-4; 61 62 template<class T>T gcd(T a, T b){return b==0?a:gcd(b,a%b);} 63 template<class T>bool max_update(T &a,const T &b){if(b>a){a = b; return true;}return false;} 64 template<class T>bool min_update(T &a,const T &b){if(b<a){a = b; return true;}return false;} 65 template<class T>T condition(bool f, T a, T b){return f?a:b;} 66 template<class T>void copy_arr(T a[], T b[], int n){rep_up0(i,n)a[i]=b[i];} 67 int make_id(int x, int y, int n) { return x * n + y; } 68 69 const int maxI = 1e8; 70 const int Len = 8; 71 72 struct BigInt { 73 vi num; 74 bool symbol; 75 BigInt() { num.clear(); symbol = 0; } 76 BigInt(int x) { symbol = 0; if (x < 0) { symbol = 1; x = -x; } num.push_back(x % maxI); if (x >= maxI) num.push_back(x / maxI); } 77 BigInt(bool s, vi x) { symbol = s; num = x; } 78 BigInt(char s[]) { 79 int len = strlen(s), x = 1, sum = 0, p = s[0] == ‘-‘; 80 symbol = p; 81 for (int i = len - 1; i >= p; i--) { 82 sum += (s[i] - ‘0‘) * x; 83 x *= 10; 84 if (x == 1e8 || i == p) { 85 num.push_back(sum); 86 sum = 0; 87 x = 1; 88 } 89 } 90 while (num.back() == 0 && num.size() > 1) num.pop_back(); 91 } 92 93 void push(int x) { num.push_back(x); } 94 95 BigInt abs() const { return BigInt(false, num); } 96 97 bool smaller(const vi &a, const vi &b) const { 98 if (a.size() != b.size()) return a.size() < b.size(); 99 for (int i = a.size() - 1; i >= 0; i--) { 100 if (a[i] != b[i]) return a[i] < b[i]; 101 } 102 return 0; 103 } 104 105 bool operator < (const BigInt &p) const { 106 if (symbol && !p.symbol) return true; 107 if (!symbol && p.symbol) return false; 108 if (symbol && p.symbol) return smaller(p.num, num); 109 return smaller(num, p.num); 110 } 111 112 bool operator > (const BigInt &p) const { 113 return p < *this; 114 } 115 116 bool operator == (const BigInt &p) const { 117 return !(p < *this) && !(*this < p); 118 } 119 120 bool operator >= (const BigInt &p) const { 121 return !(*this < p); 122 } 123 124 bool operator <= (const BigInt &p) const { 125 return !(p < *this); 126 } 127 128 vi add(const vi &a, const vi &b) const { 129 vi c; 130 c.clear(); 131 int x = 0; 132 for (int i = 0; i < a.size(); i++) { 133 x += a[i]; 134 if (i < b.size()) x += b[i]; 135 c.push_back(x % maxI); 136 x /= maxI; 137 } 138 for (int i = a.size(); i < b.size(); i++) { 139 x += b[i]; 140 c.push_back(x % maxI); 141 x /= maxI; 142 } 143 if (x) c.push_back(x); 144 while (c.back() == 0 && c.size() > 1) c.pop_back(); 145 return c; 146 } 147 148 vi sub(const vi &a, const vi &b) const { 149 vi c; 150 c.clear(); 151 int x = 1; 152 for (int i = 0; i < b.size(); i++) { 153 x += maxI + a[i] - b[i] - 1; 154 c.push_back(x % maxI); 155 x /= maxI; 156 } 157 for (int i = b.size(); i < a.size(); i++) { 158 x += maxI + a[i] - 1; 159 c.push_back(x % maxI); 160 x /= maxI; 161 } 162 while (c.back() == 0 && c.size() > 1) c.pop_back(); 163 return c; 164 } 165 166 vi mul(const vi &a, const vi &b) const { 167 vi c; 168 c.resize(a.size() + b.size()); 169 for (int i = 0; i < a.size(); i++) { 170 for (int j = 0; j < b.size(); j++) { 171 LL tmp = (LL)a[i] * b[j] + c[i + j]; 172 c[i + j + 1] += tmp / maxI; 173 c[i + j] = tmp % maxI; 174 } 175 } 176 while (c.back() == 0 && c.size() > 1) c.pop_back(); 177 return c; 178 } 179 180 vi div(const vi &a, const vi &b) const { 181 vi c(a.size()), x(1, 0), y(1, 0), z(1, 0), t(1, 0); 182 y.push_back(1); 183 for (int i = a.size() - 1; i >= 0; i--) { 184 z[0] = a[i]; 185 x = add(mul(x, y), z); 186 if (smaller(x, b)) continue; 187 int l = 1, r = maxI - 1; 188 while (l < r) { 189 int m = (l + r + 1) >> 1; 190 t[0] = m; 191 if (smaller(x, mul(b, t))) r = m - 1; 192 else l = m; 193 } 194 c[i] = l; 195 t[0] = l; 196 x = sub(x, mul(b, t)); 197 } 198 while (c.back() == 0 && c.size() > 1) c.pop_back(); 199 return c; 200 } 201 202 BigInt operator + (const BigInt &p) const{ 203 if (!symbol && !p.symbol) return BigInt(false, add(num, p.num)); 204 if (!symbol && p.symbol) return *this >= p.abs()? BigInt(false, sub(num, p.num)) : BigInt(true, sub(p.num, num)); 205 if (symbol && !p.symbol) return (*this).abs() > p? BigInt(true, sub(num, p.num)) : BigInt(false, sub(p.num, num)); 206 return BigInt(true, add(num, p.num)); 207 } 208 209 BigInt operator - (const BigInt &p) const { 210 return *this + BigInt(!p.symbol, p.num); 211 } 212 213 BigInt operator * (const BigInt &p) const { 214 BigInt res(symbol ^ p.symbol, mul(num, p.num)); 215 if (res.symbol && res.num.size() == 1 && res.num[0] == 0) res.symbol = false; 216 return res; 217 } 218 219 BigInt operator / (const BigInt &p) const { 220 if (p == BigInt(0)) return p; 221 BigInt res(symbol ^ p.symbol, div(num, p.num)); 222 if (res.symbol && res.num.size() == 1 && res.num[0] == 0) res.symbol = false; 223 return res; 224 } 225 226 BigInt operator % (const BigInt &p) const { 227 return *this - *this / p * p; 228 } 229 230 void show() const { 231 if (symbol) putchar(‘-‘); 232 printf("%d", num[num.size() - 1]); 233 for (int i = num.size() - 2; i >= 0; i--) { 234 printf("%08d", num[i]); 235 } 236 putchar(‘\n‘); 237 } 238 239 int TotalDigit() const { 240 int x = num[num.size() - 1] / 10, t = 1; 241 while (x) { 242 x /= 10; 243 t++; 244 } 245 return t + (num.size() - 1) * Len; 246 } 247 248 }; 249 typedef BigInt bi; 250 bi A, B, a, b; 251 bi x, y, d, t; 252 char s[100]; 253 void gcd(bi a, bi b, bi &d, bi &x, bi &y) { 254 if (b == 0) { 255 d = a; 256 x = 1; 257 y = 0; 258 } 259 else { 260 gcd(b, a % b, d, y, x); 261 y = y - x * (a / b); 262 } 263 } 264 265 bi f(bi k) { 266 bi p = t * x + k * b; 267 bi q = t * y - k * a; 268 if (p > 0 && q > 0 || p < 0 && q < 0) return max(p.abs(), q.abs()); 269 return p.abs() + q.abs(); 270 } 271 272 int main() { 273 //freopen("in.txt", "r", stdin); 274 int T; 275 cin >> T; 276 while (T --) { 277 cin >> s; 278 A = bi(s); 279 cin >> s; 280 B = bi(s); 281 cin >> s; 282 a = bi(s); 283 cin >> s; 284 b = bi(s); 285 t = (A - B).abs(); 286 bi g = gcd(a, b); 287 if (!(t % g == 0)) { 288 puts("-1"); 289 continue; 290 } 291 a = a / g; 292 b = b / g; 293 t = t / g; 294 295 gcd(a, b, d, x, y); 296 297 bi l = "-100000000000000000", r = "100000000000000000"; 298 while (r - l > 2) { 299 bi m1 = l + (r - l) / 3, m2 = r - (r - l) / 3; 300 if (f(m1) > f(m2)) l = m1 + 1; 301 else r = m2; 302 } 303 bi ans = f(l); 304 min_update(ans, f(l + 1)); 305 min_update(ans, f(l + 2)); 306 ans.show(); 307 } 308 }
标签:
原文地址:http://www.cnblogs.com/jklongint/p/4480791.html