【组合数学+二叉树】ABC220 E - Distance on Large Perfect Binary Tree

妈 的这辈子学不会计数

急死我了急死我了急死我了

E - Distance on Large Perfect Binary Tree (atcoder.jp)

题意:

思路:

特殊的地方:

D只有2e6

完全二叉树

树上路径

2^N-1很大很大,因此肯定是组合计数问题

因为2e6的数据,大概率复杂度就是O(d)的 

考虑枚举路径所经最高层结点的左右链分配的长度

设左链长度为l,右链为d-l

然后结点位置还不确定

该结点只会存在于前n-max(l,d-l)层的树上,因此有(2^n-max(l,d-l))-1种情况

这些确定了之后,由于往下走是往左还是往右不确定,因此也要计数

具体式子如下:

Code:

#include <bits/stdc++.h>
using namespace std;

constexpr int MOD = 998244353;

int norm(int x) { if (x < 0) { x += MOD; } if (x >= MOD) { x -= MOD; } return x; }
template<class T> T binpow(T a, int b) { T res = 1; for (; b; b /= 2, a *= a) { if (b % 2) { res *= a; } } return res; }

struct Z {
    int x;
    Z(int x = 0) : x(norm(x)) {}
    int val() const { return x; }
    Z operator-() const { return Z(norm(MOD - x)); }
    Z inv() const { assert(x != 0); return binpow(*this, MOD - 2); }
    Z &operator*=(const Z &rhs) { x = 1LL * x * rhs.x % MOD; return *this; }
    Z &operator+=(const Z &rhs) { x = norm(x + rhs.x); return *this; }
    Z &operator-=(const Z &rhs) { x = norm(x - rhs.x); return *this; }
    Z &operator/=(const Z &rhs) { return *this *= rhs.inv(); }
    friend Z operator*(const Z &lhs, const Z &rhs) { Z res = lhs; res *= rhs; return res; }
    friend Z operator+(const Z &lhs, const Z &rhs) { Z res = lhs; res += rhs; return res; }
    friend Z operator-(const Z &lhs, const Z &rhs) { Z res = lhs; res -= rhs; return res; }
    friend Z operator/(const Z &lhs, const Z &rhs) { Z res = lhs; res /= rhs; return res; }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    int d;
    cin >> d;
    Z ans = 0;
    for (int i = 0; i <= d; i++) {
        int dep = n - max(i, d - i);
        if (dep >= 1) {
            ans += (binpow(Z(2), dep) - 1) * binpow(Z(2), max(0, i - 1)) * binpow(Z(2), max(0, d - i - 1));
        }
    }
    ans *= 2;
    cout << ans.val() << "\n";
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值