码迷,mamicode.com
首页 > 其他好文 > 详细

[zoj3593]扩展欧几里得+三分

时间:2015-05-06 06:50:46      阅读:584      评论:0      收藏:0      [点我收藏+]

标签:

题意:给一个数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 }
View Code

 

[zoj3593]扩展欧几里得+三分

标签:

原文地址:http://www.cnblogs.com/jklongint/p/4480791.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!