首页 > 其他分享 >[题解] Codeforces Round 900(Div.3) E~F

[题解] Codeforces Round 900(Div.3) E~F

时间:2023-09-27 20:00:44浏览次数:32  
标签:std __ 900 SparseTable int 题解 Codeforces auto oper

Codeforces Round 900(Div.3) E~F

E. Iva & Pav

因为按位与的结果不会随着越多数字的增加而增加,因此我们可以利用这个性质二分出右端点,只需要一个可以查询区间的数据结构即可。

或者是按位考虑第 \(i\) 个数字的第 \(k\) 位,后缀最近的 \(0\) 的位置,按位考虑也可以。但是这题使用二分会比较更好地考虑。

template <typename _Ty, typename _Oper>
class SparseTable {
private:
    std::vector<std::vector<_Ty>> _f;
    _Oper _oper;
    std::size_t _n;

public:
    using value_type = _Ty;
    using operator_type = _Oper;

private:
    explicit SparseTable(std::size_t n, _Ty value, _Oper oper)
        : _f(std::bit_width(n), std::vector<_Ty>(n, value)),
          _oper(std::move(oper)), _n(n) {}

public:
    template <std::input_iterator __Iter, typename __Oper>
        requires requires(typename std::iterator_traits<__Iter>::value_type x,
                          __Oper oper) {
            {
                oper(x, x)
            }
            -> std::same_as<typename std::iterator_traits<__Iter>::value_type>;
        }
    explicit SparseTable(__Iter first, __Iter last, __Oper oper)
        : SparseTable(std::distance(first, last),
                      (typename __Iter::value_type){}, std::move(oper)) {
        std::copy(first, last, _f[0].begin());

        for (std::size_t i = 1; i < _f.size(); i++) {
            for (std::size_t j = 0; j + (1 << i) - 1 < _n; j++) {
                _f[i][j] = _oper(_f[i - 1][j], _f[i - 1][j + (1 << (i - 1))]);
            }
        }
    }

    auto Ask(std::size_t l, std::size_t r) const -> _Ty {
        auto s = std::bit_width(r - l) - 1;
        return _oper(_f[s][l], _f[s][r - (1 << s)]);
    }

    auto Size() const noexcept -> std::size_t {
        return _n;
    }
};

template <typename __Iter, typename __Oper>
explicit SparseTable(__Iter, __Iter, __Oper)
    -> SparseTable<typename std::iterator_traits<__Iter>::value_type, __Oper>;

void Main() {
    int n;
    std::cin >> n;
    
    std::vector<int> a(n);
    for (auto &x : a) {
        std::cin >> x;
    }

    SparseTable st(a.begin(), a.end(), std::bit_and{});
    auto GetLast = [&](int first, int k) -> int {
        int l = first + 1, r = n, last = -1;
        while (l <= r) {
            auto mid = std::midpoint(l, r);
            if (st.Ask(first, mid) >= k) {
                last = mid;
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }
        return last;
    };

    int q;
    std::cin >> q;
    for (int t = 0; t < q; t += 1) {
        int l, k;
        std::cin >> l >> k;
        l -= 1;
        std::cout << GetLast(l, k) << " \n"[t + 1 == q];   
    }
}

F. Vasilije Loves Number Theory

由唯一分解定理,可得 \(n = \prod_{i=1}^{m} p_{i}^{a_i}\) ,其因子个数 \(d(n) = \prod_{i=1}^{m}(a_i + 1)\) 。

因为 \(d(x)\) 是积性函数,所以有 \(d(ab) = d(a)d(b)\) 。

题目要问是否存在一个数 \(a\) ,使得 \(\gcd(a, n) = 1\) 且 \(d(an) = n\) 。对于后者,我们可以将其改写为 \(n = d(a)d(n)\) ,则此时有 \(d(a) = \cfrac{n}{d(n)}\) 。由于因子个数一定是一个正整数,因此,存在一个合法的 \(a\) 的前提条件就自然是 \(d(n) \mid n\) 。

那么我们要怎么确定可以从求得的 \(d(a)\) 知道是否能够构造出一个合法的 \(a\) 呢?很简单,只需要挑几个非常大的素数,能够构成 \(a\) 即可,此时两个数的因子集合没有交集,自然满足 \(\gcd(a, n) = 1\) 了。

最后一个问题: \(n\) 可能过大,怎么办?

我们发现,给定的 \(q\) 很小,小到甚至我们每次做一次 \(O(\sqrt x)\) 的质因数分解,都不会超时,因此,我们可以将 \(n\) 分解,对于之后的 \(x\) 也是分解,并添加进之前分解的结果中。

此时我们要知道 \(d(n) \mid n\) 是否成立,只需要先计算出 \(d(n)\) ,然后看是否 \(d(n)\) 分解后是否是 \(n\) 的子集,即可。

void Main() {
    int n, q;
    std::cin >> n >> q;

    auto Calc = [](auto &mp, auto n, auto d) {
        for (int i = 2; i * i <= n; i += 1) {
            if (n % i == 0) {
                int cnt = 0;
                while (n % i == 0) {
                    n /= i;
                    cnt += 1;
                }
                d /= mp[i] + 1;
                d *= (mp[i] += cnt) + 1;
            }
        }
        if (n > 1) {
            d /= mp[n] + 1;
            d *= (mp[n] += 1) + 1;
        }
        return d;
    };

    std::map<int,int> pre;
    i64 pred = Calc(pre, n, i64(1));

    auto mp = pre;
    auto d = pred;
    
    for (int t = 0; t < q; t += 1) {
        int opt;
        std::cin >> opt;

        if (opt == 1) {
            int x;
            std::cin >> x;
            d = Calc(mp, x, d);

            auto tmp = d;
            for (auto [x, y] : mp) {
                while (y > 0 && tmp % x == 0) {
                    tmp /= x;
                    y --;
                }
            }

            if (tmp == 1) {
                std::cout << "YES\n";
            } else {
                std::cout << "NO\n";
            }
        } else {
            mp = pre;
            d = pred;
        }
    }
    std::cout << '\n';
}

标签:std,__,900,SparseTable,int,题解,Codeforces,auto,oper
From: https://www.cnblogs.com/FlandreScarlet/p/17734183.html

相关文章

  • ACAM 学习笔记 | 附 YbtOJ 全部题解
    怎么有人现在才学ACAM呢。好像比SAM简单挺多啊,也不记得当时是哪里看不懂。AC自动机(✔)自动AC机(✘)概述ACAM(Aho–CorasickAutomaton),是用来解决多模式串匹配的字符串算法。它的结构是个DAG,其中点表示状态,边表示转移。这一点上各种自动机都是相同的。具体来说,可以感性......
  • [题解]CF1878E Iva & Pav
    CF是没题考了吧,每场都出二进制拆位。思路首先我们可以二分\(r\),因为\(r\)越大,按位与一定只会小于等于\(r\)小的情况。那么,我们可以用\(num_{i,j}\)记录\(a_j\)第\(i\)位的二进制情况。如果我们对\(num_{i,j}\)做一个前缀和,如果\(num_{i,r}-num_{i,l-1}=r......
  • B. Amr and Pins( Codeforces Round #287 (Div. 2))
    #include<stdio.h>#include<string.h>#include<stdlib.h>#include<math.h>intmain(){doubler,x1,y1,x2,y2;while(scanf("%lf%lf%lf%lf%lf",&r,&x1,&y1,&x2,&y2)!=EOF){doubleaa=sq......
  • C. Anya and Ghosts(Codeforces Round #288 (Div. 2))
    #include<iostream>#include<algorithm>#include<stdio.h>#include<string.h>#include<stdlib.h>usingnamespacestd;structnode{intx;inty;}q[3010];inta[3001];intn,m,k;intmain(){while(scanf("......
  • C. Anya and Ghosts( Codeforces Round #288 (Div. 2))
    #include<iostream>#include<algorithm>#include<stdio.h>#include<string.h>#include<stdlib.h>usingnamespacestd;structnode{intx;inty;}q[3010];inta[3001];intn,m,k;intmain(){while(scanf("......
  • 安装 SonarQube后sonarqube-sonarqube无法启动的问题解决
    1.前言我的环境:k8s集群(version1.23.6),安装了Kubesphere(versionv3.4)作为可视化界面,最近想要推动团队走CICD,于是在Kubesphere中启用了devops组件,参考:https://kubesphere.io/zh/docs/v3.4/pluggable-components/devops/。组件安装完成后,需要将Sonarqube集成到流水线中,于是又安装......
  • luogu P4819 [中山市选] 杀人游戏 题解 【强连通分量+缩点】
    目录题目链接思路分析代码题目链接P4819思路分析首先考虑这道题的连通性。容易发现这种类型的题目会容易产生环形的状态转移。假设我们知道了其中的一个点是否是黑白点,那么我们就可以知道所有点是否是黑白点。容易陷入一个误区:我们只能通过一个点知道他所相邻的最直接的点,如何......
  • CF1878 A-G 题解
    前言赛时代码可能比较难看。A判定\(a\)中是否有\(k\)即可。赛时代码B奇怪的构造题。令\(a_1=1,a_2=3\),其他项由上一项加一开始枚举判定可行性即可,可以简单证明时间复杂度为\(O(n)\)。赛时代码C容易发现当\(x\in\left[\dfrac{k(k+1)}{2},\dfrac{k(2n-k+1)}{2}\ri......
  • 【UVA 536】Tree Recovery 题解(根据遍历序列还原二叉树)
    小瓦伦丁非常喜欢玩二叉树。她最喜欢的游戏是随机构建查找节点中带有大写字母的二叉树。这是她创作的一个例子:为了给后代记录她的树,她为每棵树写下了两个字符串:预订单遍历(根、左子树、右子树)和有序遍历(左子树、根、右子树。对于上面绘制的树,预序遍历是DBACEGF,有序遍历是ABCDEFG......
  • Codeforces Round 900 (Div. 3)
    昨天晚上生病,没比(血亏)A:就是看k有没有在序列里B:随便放一个大的号码然后加i,应该就可以过了C:就是我们最少要拿k*(k+1)/2,最多可以拿k*(n+n-k+1)/2。啊,你问我怎么证明在这两个值里就一定可以拿到(当然是猜的!!)D:让f[x]表示当前出了多少次。然后就没个k看l[i],r[i]和j有没......