zoukankan      html  css  js  c++  java
  • 7.23

    省选班Day1

    Naughty Fairies

    虽然我的做法T了,但是那应该让高精度背锅(多了个N就T了)

    大概和老师算法差不多?(为什么我的这么不像dp)

    首先将数转换为二进制

    那能不能直接贪心?

    发现我们如果是目标的前缀,那么只需要把*2和+1/0交替就行了

    Is that right?

    hack: 1111 11111

    因为有了 (-1) 操作,发现贪心不能保证正确性,GG了

    但是这同样启发我们成为目标的前缀和前缀 (+1) 同样重要

    这样就可以 (DP) 了(是不是很神奇)

    (dp[i][j]) 表示当前处理到第 (i) 位 是前缀或前缀 (+1) )

    转移:

    [if ~(b[i]=0)~ dp[i][0]=min(dp[i-1][0]+1,dp[i-1][1]+2),dp[i][1]=min(dp[i-1][0]+2,dp[i-1][1]+2)\ else ~dp[i][0]=min(dp[i-1][0]+2,dp[i-1][1]+2), dp[i][1]=min(dp[i-1][0]+2,dp[i-1][1]+1)\ ]

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define cls(a) memset(a, 0, sizeof(a))
    #define rise(i, a, b) for (int i = a; i <= b; i++)
    #define fall(i, a, b) for (int i = a; i >= b; i--)
    const int base = 1e9;
    char a[600];
    bool ined, flag;
    int cnt, cntt, ep;
    void init() {
        ined = false;
        cnt = 0;
        while (true) {
            a[cnt] = getchar();
            if (a[cnt] >= '0' && a[cnt] <= '9') {
                ined = true;
                cnt++;
            } else if (ined)
                break;
        }
        a[cnt] = '';
        cnt--;
    }
    struct point {
        int num[60], len;
        point() { clear(); }
        void clear() {
            len = 1;
            cls(num);
        }
        void out(int x) {
            printf("%d", num[len]);
            fall(i, len - 1, 1) printf("%09d", num[i]);
            if (x)
                putchar('
    ');
            else
                putchar(' ');
        }
        void in() {
            init();
            cntt = 0;
            ep = 1;
            clear();
            fall(i, cnt, 0) {
                if (cntt == 9) {
                    cntt = 0;
                    len++;
                    ep = 1;
                }
                cntt++;
                num[len] += (int)(a[i] - '0') * ep;
                ep *= 10;
            }
            while (len > 1 && num[len] == 0) len--;
        }
        void inc() {
            num[1]++;
            rise(i, 1, len) {
                if (num[i] >= base) {
                    num[i + 1]++;
                    num[i] -= base;
                } else
                    break;
            }
            if (num[len + 1] == 1)
                len++;
        }
        void dec(int x) {
            num[1] -= x;
            rise(i, 1, len) {
                if (num[i] < 0) {
                    num[i + 1]--;
                    num[i] += base;
                } else
                    break;
            }
            if (num[len] == 0)
                len--;
        }
        void divid() {
            fall(i, len, 1) {
                num[i - 1] += (num[i] & 1) * base;
                num[i] >>= 1;
            }
            if (num[len] == 0)
                len--;
        }
        point &operator=(const point &);
        point operator-(const point &) const;
        point operator+(const point &) const;
        point(const int);
        bool operator>(const point &p) const;
        bool operator<(const point &p) const;
        bool operator==(const point &p) const;
    } n, m, one, zero, two, now[3], tmp[5], nv[3], tv[5], ans;
    point &point ::operator=(const point &p) {
        clear();
        len = p.len;
        rise(i, 1, len) num[i] = p.num[i];
        return *this;
    }
    point point ::operator+(const point &p) const {
        point ret = *this;
        int l = max(ret.len, p.len);
        rise(i, 1, l) {
            ret.num[i] += p.num[i];
            if (ret.num[i] >= base) {
                ret.num[i + 1]++;
                ret.num[i] -= base;
            }
        }
        if (ret.num[l + 1] > 0)
            l++;
        ret.len = l;
        return ret;
    }
    point point ::operator-(const point &p) const {
        point ret = *this;
        if (ret > p) {
            rise(i, 1, ret.len) {
                ret.num[i] -= p.num[i];
                if (ret.num[i] < 0) {
                    ret.num[i] += base;
                    ret.num[i + 1]--;
                }
            }
            while (ret.len > 1)
                if (ret.num[ret.len] == 0)
                    ret.len--;
                else
                    break;
            return ret;
        }
        if (ret == p)
            return zero;
        if (ret < p) {
            point tmp = ret;
            ret = p;
            rise(i, 1, ret.len) {
                ret.num[i] -= tmp.num[i];
                if (ret.num[i] < 0) {
                    ret.num[i] += base;
                    ret.num[i + 1]--;
                }
            }
            while (ret.len > 1)
                if (ret.num[ret.len] == 0)
                    ret.len--;
                else
                    break;
            return ret;
        }
    }
    point::point(const int b) {
        clear();
        num[1] = b;
    }
    bool point::operator==(const point &p) const {
        if (len != p.len)
            return false;
        fall(i, len, 1) if (num[i] != p.num[i]) return false;
        return true;
    }
    bool point::operator>(const point &p) const {
        if (len > p.len)
            return true;
        if (len < p.len)
            return false;
        fall(i, len, 1) {
            if (num[i] > p.num[i])
                return true;
            if (num[i] < p.num[i])
                return false;
        }
        return false;
    }
    bool point::operator<(const point &p) const {
        if (len < p.len)
            return true;
        if (len > p.len)
            return false;
        fall(i, len, 1) {
            if (num[i] < p.num[i])
                return true;
            if (num[i] > p.num[i])
                return false;
        }
        return false;
    }
    
    int main() {
        one = point(1);
        zero = point(0);
        two = point(2);
        int cnt = 1;
        while (true) {
            m.in();
            n.in();
            if (n == zero && m == zero)
                break;
            if (n > m || n == m) {
                (n - m).out(1);
                continue;
            }
            now[1] = m;
            ans = m - n;
            cnt = 1;
            cntt = 0;
            while (cnt) {
                rise(i, 1, cnt) {
                    if (ans > now[i] - n + nv[i])
                        ans = now[i] - n + nv[i];
                    if (now[i].num[1] % 2 == 0) {
                        flag = 0;
                        rise(j, 1, cntt) if (now[i] == tmp[j]) {
                            if (nv[i] < tv[j])
                                tv[j] = nv[i];
                            flag = true;
                        }
                        if (!flag) {
                            tmp[++cntt] = now[i];
                            tv[cntt] = nv[i];
                        }
                    } else {
                        nv[i].inc();
                        flag = false;
                        now[i].inc();
                        rise(j, 1, cntt) if (now[i] == tmp[j]) {
                            if (nv[i] < tv[j])
                                tv[j] = nv[i];
                            flag = true;
                        }
                        if (!flag) {
                            tmp[++cntt] = now[i];
                            tv[cntt] = nv[i];
                        }
    
                        if (now[i] > two) {
                            flag = false;
                            now[i].dec(2);
                            rise(j, 1, cntt) if (now[i] == tmp[j]) {
                                if (nv[i] < tv[j])
                                    tv[j] = nv[i];
                                flag = true;
                            }
                            if (!flag) {
                                tmp[++cntt] = now[i];
                                tv[cntt] = nv[i];
                            }
                        }
                    }
                    now[i].clear();
                    nv[i].clear();
                }
                cnt = 0;
                rise(i, 1, cntt) {
                    if ((tmp[i].len > 1 || tmp[i].num[1] > 2) && tmp[i] > n) {
                        tmp[i].divid();
                        nv[++cnt] = tv[i] + one;
                        now[cnt] = tmp[i];
                    }
                    tmp[i].clear();
                    tv[i].clear();
                }
                cntt = 0;
            }
            ans.out(1);
        }
        return 0;
    }
    
  • 相关阅读:
    [NOIP2012] 开车旅行
    八皇后
    [Noip2014] 解方程
    [Noip2012] 国王游戏
    [JZOJ4685] 【NOIP2016提高A组8.12】礼物
    [JZOJ100043] 【NOIP2017提高A组模拟7.13】第K小数
    大整数类模板
    [BZOJ2460] [BeiJing2011]元素
    [BZOJ5299] [CQOI2018]解锁屏幕
    [JZOJ4737] 【NOIP2016提高A组模拟8.25】金色丝线将瞬间一分为二
  • 原文地址:https://www.cnblogs.com/harryhqg/p/SXBDay1.html
Copyright © 2011-2022 走看看