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;
    }
    
  • 相关阅读:
    轻重搭配
    EF的优缺点
    使用bootstrap-select有时显示“Nothing selected”
    IIS发布 HTTP 错误 500.21
    js添加的元素无法触发click事件
    sql server查看表是否死锁
    sql server把一个库表的某个字段更新到另一张表的相同字段
    SQLSERVER排查CPU占用高的情况
    SQL server中如何按照某一字段中的分割符将记录拆成多条
    LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.
  • 原文地址:https://www.cnblogs.com/harryhqg/p/SXBDay1.html
Copyright © 2011-2022 走看看