zoukankan      html  css  js  c++  java
  • [zoj3593]扩展欧几里得+三分

    题意:给一个数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
    ", 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('
    ');
    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
  • 相关阅读:
    flask 使用 SQLAlchemy 的两种方式
    python package 的两种组织方式
    sqlalchemy 的 raw sql 方式使用示例
    Git高速入门——Git安装、创建版本号库以及经常使用命令
    mariadb 10.1.10安装
    Android studio中导入第三方类库
    怎样获取oracle dbid
    宇宙中为何存在“黑洞”?
    CSDN日报20170401 ——《假设你还是“程序猿”,我劝你别创业!》
    clang-format中文出错
  • 原文地址:https://www.cnblogs.com/jklongint/p/4480791.html
Copyright © 2011-2022 走看看