zoukankan      html  css  js  c++  java
  • 【数论&线段树】【P4140】[清华集训2015]奇数国

    Description

    有一个长为 (n) 的序列,保证序列元素不超过 (10^6) 且其质因数集是前60个质数集合的子集。初始时全部都是 (3),有 (m) 次操作,要么要求支持单点修改,要么要求查询区间 ([l,~r]) 的区间积 (x) 的欧拉函数值 (phi(x)) 对一个质数取模的结果。

    Limitation

    (1 leq n,~m leq 10^5)

    Solution

    考虑一个公式

    [phi(x) = prod_{i = 1}^{60} p_i^{c_i - 1} imes (p_i - 1) ]

    证明上,考虑 (phi(p) = p - 1),其中 (p) 是一个质数,那么对于 (p^k),由于它有且仅有 (p) 一个因数,于是 (p^k) 共有 (frac{p^k}{p} = p^{k - 1}) 个因数,于是 (phi(p^k)~=~p^k - p^{k - 1}~=~p^{k-1} imes (p - 1))

    由于欧拉函数是积性的,将每个质因子的欧拉函数乘起来即可得到上式。

    于是考虑用线段树维护区间积,再状压维护区间每个质因数的出现情况,对于出现的质因数 (p),查询时直接将区间积乘上 (p^{-1} imes (p - 1)) 即可。

    Code

    #include <cstdio>
    #include <algorithm>
    
    const int maxn = 100005;
    const int MOD = 19961993;
    
    int n = 100000, q;
    const int prm[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281};
    const int inv[] = {9980997, 6653998, 11977196, 8555140, 5444180, 1535538, 10568114, 14708837, 3471651, 11701858, 17386252, 1618540, 16066970, 2321162, 18263100, 16948862, 12518538, 15380552, 10725847, 1686929, 13399146, 17182475, 12025297, 15924736, 13582387, 395287, 6395590, 15857658, 16299242, 6359573, 3300802, 18742940, 6702567, 10914471, 16210746, 11765678, 5340151, 18247466, 7769638, 8077107, 11932588, 6506948, 1985748, 6619521, 5877135, 4413707, 9744480, 10115270, 14597757, 16475182, 18334191, 5011379, 18885205, 7555336, 621385, 11309266, 12170137, 12006660, 18304499, 11153142};
    
    struct Tree {
      int l, r;
      ll v, oc;
      Tree *ls, *rs;
    
      Tree() : v(3), oc(2), ls(NULL), rs(NULL) {}
    
      inline void pushup() {
        this->v = this->ls->v * this->rs->v % MOD;
        this->oc = this->ls->oc | this->rs->oc;
      }
      
      inline bool inrange(const int l, const int r) { return (this->l >= l) && (this->r <= r); }
      inline bool outofrange(const int l, const int r) { return (this->l > r) || (this->r < l); }
    };
    Tree *rot;
    
    void build(Tree *const u, const int l, const int r);
    void update(Tree *const u, const int p, const int v);
    std::pair<ll, ll> query(Tree *const u, const int l, const int r);
    
    int main() {
      freopen("1.in", "r", stdin);
      qr(q);
      build(rot = new Tree, 1, n);
      int a, b, c;
      while (q--) {
        a = b = c = 0; qr(a); qr(b); qr(c);
        if (a == 0) {
          auto _ret = query(rot, b, c);
          for (int i = 0; i < 60; ++i) if (_ret.second & (1ll << i)) {
            _ret.first = _ret.first * inv[i] % MOD * (prm[i] - 1) % MOD;
          }
          qw(_ret.first, '
    ', true);
        } else {
          update(rot, b, c);
        }
      }
      return 0;
    }
    
    void build(Tree *const u, const int l, const int r) {
      if ((u->l = l) == (u->r = r)) return;
      int mid = (l + r) >> 1;
      build(u->ls = new Tree, l, mid);
      build(u->rs = new Tree, mid + 1, r);
      u->pushup();
    }
    
    std::pair<ll, ll> query(Tree *const u, const int l, const int r) {
      if (u->inrange(l, r)) {
        return std::make_pair(u->v, u->oc);
      } else if (u->outofrange(l, r)) {
        return std::make_pair(1ll, 0ll);
      } else {
        auto lr = query(u->ls, l, r), rr = query(u->rs, l, r);
        return std::make_pair(lr.first * rr.first % MOD, lr.second | rr.second);
      }
    }
    
    void update(Tree *const u, const int p, const int v) {
      if (u->outofrange(p, p)) {
        return;
      } else if (u->l == u->r) {
        u->v = v; u->oc = 0;
        for (int i = 0; i < 60; ++i) if (!(v % prm[i])) {
          u->oc |= 1ll << i;
        }
      } else {
        update(u->ls, p, v); update(u->rs, p, v);
        u->pushup();
      }
    }
    
  • 相关阅读:
    CDQZ Day5
    CDQZ Day4
    CDQZ Day3
    POJ 2226 Muddy Fields
    【其他】【生成图片】【1】通过phantomjs 进行页面截图
    【Redis】【1】一些报错处理
    【Java】【15】判断url对应的图片是否存在
    【HTML&CSS】【3】点击直接发送邮件
    【微信公众号开发】【16】遇到的问题
    【Oracle】【9】取前N条记录——rownum和row_number() over()的使用
  • 原文地址:https://www.cnblogs.com/yifusuyi/p/11186955.html
Copyright © 2011-2022 走看看