ABC340

C

黑板上给一个数N,一直不停重复到黑板上的数组里面只剩下1:
擦去每个大于1的数n
加入 ⌊ n 2 ⌋ 和 ⌈ n 2 ⌉ \lfloor \frac n 2 \rfloor和 \lceil \frac n 2 \rceil 2n2n
每擦一个数n计入分数n
求最后的总分数


用map记录一下每个n的总得分

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;


ll n;
map<ll, ll> h;

ll get(ll x) {
    if (h.count(x)) return h[x];
    if (x == 1) return 0;
    if (x % 2 == 0) {
        return h[x] = get(x / 2) * 2 + x;
    }
    else {
        return h[x] = get(x / 2) + get(x / 2 + 1) + x;
    }
}


int main(){
    //freopen("in.txt", "r", stdin);
    cin >> n;
    ll ans = get(n);
    printf("%lld\n", ans);
    return 0;
}

D

1…N的一个数组,一开始在格子1
对于格子i有两个操作,一个花费 A i A_i Ai到i+1,第二个花费 B i B_i Bi到d
求最后到N的最小花费


优先队列

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

int n;
int a[200020], b[200020], x[200020];
ll f[200020];
vector<pair<int, ll>> g[200020];

struct Node {
    ll w;
    int u;
    bool operator < (const Node& rhs) const {
        return w > rhs.w;
    }
};


int main(){
    //freopen("in.txt", "r", stdin);
    cin >> n;
    memset(f, 0x33, sizeof(f));
    f[1] = 0;
    for (int i = 1; i < n; ++i) {
        cin >> a[i] >> b[i] >> x[i];
        g[i].push_back({ x[i], b[i] });
        g[i].push_back({ i + 1, a[i] });
    }
    priority_queue<Node> qu;
    qu.push({ 0, 1 });
    while (qu.size()) {
        auto [w, u] = qu.top();
        qu.pop();
        if (u == n) {
            break;
        }
        for (auto [v, tw]: g[u]) {
            if (w + tw < f[v]) {
                f[v] = w + tw;
                qu.push({ f[v], v });
            }
        }
    }
    printf("%lld\n", f[n]);
    return 0;
}

E

围成一圈的n个格子,每个格子里都放着 A i A_i Ai个球
m个操作,格子 M i M_i Mi
将格子里面的球拿出来,按顺序依次放到所有格子里面,每次放一个
求最后每个格子里有几个球


对单点更新(清零)–就是区间更新,单点查询,裸的线段树。BIT+差分也可。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

int n, m;
const int N = 200020;
ll a[N];
#define lu (u * 2)
#define ru (u * 2 + 1)

struct SegTree {
    struct Node {
        int l, r;
        ll val, add;
    }tr[N << 2];

    void push_down(int u) {
        if (tr[u].add) {
            tr[lu].add += tr[u].add;
            tr[ru].add += tr[u].add;
            tr[u].add = 0;
        }
    }

public:
    void build(int l, int r, int u) {
        tr[u].l = l, tr[u].r = r, tr[u].add = 0;
        if (l == r) {
            tr[u].val = a[l];
            return;
        }
        int mi = (l + r) / 2;
        build(l, mi, lu);
        build(mi + 1, r, ru);
    }

    void update(int l, int r, int u, ll v) {
        if (l <= tr[u].l && tr[u].r <= r) {
            tr[u].add += v;
            return;
        }
        push_down(u);
        int mi = (tr[u].l + tr[u].r) / 2;
        if (mi >= l)
            update(l, r, lu, v);
        if (mi < r) 
            update(l, r, ru, v);
    }

    ll query(int p, int u) {
        if (tr[u].l == tr[u].r) {
            return tr[u].val + tr[u].add;
        }
        push_down(u);
        int mi = (tr[u].l + tr[u].r) / 2;
        if (p <= mi) 
            return query(p, lu);
        else 
            return query(p, ru);
    }
} seg;


int main(){
    //freopen("in.txt", "r", stdin);
    cin >> n >> m;
    for (int i = 1; i <= n; ++i) cin >> a[i];
    seg.build(1, n, 1);
    for (int i = 0; i < m; ++i) {
        int t;
        cin >> t;
        t++;
        ll c = seg.query(t, 1);
        seg.update(t, t, 1, -c);
        seg.update(1, n, 1, c / n);
        ll r = c % n;
        if (r) {
            if (t + r <= n) {
                seg.update(t + 1, t + r, 1, 1);
            }
            else {
                if (t < n) {
                    seg.update(t + 1, n, 1, 1);
                }
                seg.update(1, r - (n - t), 1, 1);
            }
        }
        
    }
    for (int i = 1; i <= n; ++i) {
        ll c = seg.query(i, 1);
        printf("%lld ", c);
    }
    printf("\n");
    return 0;
}

F

给(0,0)点和(X,Y)点,求任意(A,B)点使得三角形面积为1


三角形面积公式
x 1 y 2 + x 2 y 3 + x 3 y 1 − x 1 y 3 − x 2 y 1 − x 3 y 2 = S x_1y_2+x_2y_3+x_3y_1-x_1y_3-x_2y_1-x_3y_2=S x1y2+x2y3+x3y1x1y3x2y1x3y2=S
化简为 a y − b x = 2 ay-bx=2 aybx=2
扩展欧几里得做就好了

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <map>
#include <set>
#include <vector>
#include <queue>
#include <stack>
#include <unordered_map>
#include <algorithm>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;

ll X, Y;
// ax - by = 2

ll gcd(ll a, ll b) {
    if (a < b) swap(a, b);
    if (b == 0) return a;
    return gcd(b, a % b);
}

ll exgcd(ll a, ll b, ll& x, ll& y) {
    if (b == 0) {
        x = 1, y = 0;
        return a;
    }
    ll x0, y0;
    ll d = exgcd(b, a % b, x0, y0);
    // b x0 + a%b y0 = d
    // b x0 + (a - (a / b)b) y0 = d
    // b x0 + a y0 - (a / b) b y0 = d
    // b(x0 - (a/b) y0) + a y0 = d
    // by + ax = d
    // y = x0 - (a/b)y0, x = y0
    y = x0 - (a / b) * y0, x = y0;
    return d;
}


int main(){
    //freopen("in.txt", "r", stdin);
    cin >> X >> Y;
    ll lx = abs(X), ly = abs(Y);
    ll d = gcd(lx, ly);
    
    if (d > 2) {
        printf("-1\n");
        return 0;
    }
    ll x, y;
    exgcd(X, Y, y, x);
    y = -y;
    if (d == 1) {
        printf("%lld %lld\n", x * 2, y * 2);
    }
    else {
        printf("%lld %lld\n", x, y);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值