首页 > 其他分享 >2021 ICPC 网络赛 第二场 L Euler Function(势能线段树,欧拉函数,状态压缩)

2021 ICPC 网络赛 第二场 L Euler Function(势能线段树,欧拉函数,状态压缩)

时间:2024-07-16 20:51:58浏览次数:18  
标签:Function phi int sum tr ICPC 2021 mul ql

2021 ICPC 网络赛 第二场 L Euler Function

题意

给定序列,定义两个操作

  • \(l,r,x\)对区间\([l,r]\)的数乘\(x\)
  • \(l,r\)求\(\sum \phi {a}_{i}\)

思路

注意欧拉函数的性质,若\(i\bmod p= 0\),\(\phi (i * p)=p*\phi (i)\),否则\(\phi(i * p) = (p - 1) * \phi (i)\)

因为\(x,w\)的值都小于\(100\),因此我们可以对线段树维护区间所有质因子的交集,当区间内交集有\(prime\),那么直接对区间乘\(prime\),否则递归到叶子节点,乘\(prime - 1\)(次数不会很多)

实现可以考虑直接用std::bitset维护每个区间的质因子状态,我这里用的是离散化之后再状压。

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

#define int long long
const int N = 1e5 + 10;
int a[N];
std::vector<int> minp, primes;
vector<int> fac[110];
int id[110], phi[110];
const int mod = 998244353;
struct node {
    int sum;
    int mul;
    int st;
}tr[N << 2];
void sieve(int n) {
    minp.assign(n + 1, 0);
    primes.clear();
    
    phi[1] = 1;
    for (int i = 2; i <= n; i++) {
        if (minp[i] == 0) {
            minp[i] = i;
            id[i] = primes.size();
            primes.push_back(i);
            phi[i] = i - 1;
        }
        
        for (auto p : primes) {
            if (i * p > n) {
                break;
            }
            minp[i * p] = p;
            if (p == minp[i]) {
                phi[i * p] = phi[i] * p;
                break;
            } else {
                phi[i * p] = phi[i] * (p - 1);            
            }
        }
    }
}
void pushup(node &u, node &l, node &r) {
    u.sum = (l.sum + r.sum) % mod;
    u.st = l.st & r.st;
}
void pushup(int k) {
    pushup(tr[k], tr[k + k], tr[k + k + 1]);
}
void pushdown(int k) {
    if (tr[k].mul > 1) {
        auto &u = tr[k], &l = tr[k + k], &r = tr[k + k + 1];
        int x = u.mul;
        l.sum = l.sum * x % mod;
        r.sum = r.sum * x % mod;
        l.mul = l.mul * x % mod;
        r.mul = r.mul * x % mod;
        u.mul = 1;
    }
}
void build(int k, int l, int r) {
    tr[k].mul = 1;
    if (l == r) {
        tr[k].sum = phi[a[l]];
        for (auto &x : fac[a[l]]) tr[k].st |= (1ll << id[x]);
        return ;
    }
    int mid = l + r >> 1;
    build(k + k, l, mid);
    build(k + k + 1, mid + 1, r);
    pushup(k);
}
void rangemodify(int k, int l, int r, int ql, int qr, int w) {
    if (l == r) {
        if ((tr[k].st & (1ll << id[w]))) {
            tr[k].sum *= w;
            tr[k].sum %= mod;
        } else {
            tr[k].sum *= w - 1;
            tr[k].sum %= mod;
        }
        tr[k].st |= (1 << id[w]);
        return ;
    }
    if (l >= ql && r <= qr) {
        //关键,只有该区间完全包含这个质因子才retrun,否则继续递归下去
        if ((tr[k].st & (1ll << id[w]))) {
            tr[k].mul = tr[k].mul * w % mod;
            tr[k].sum = tr[k].sum * w % mod;
            return ;
        }
    }
    pushdown(k);
    int mid = l + r >> 1;
    if (ql <= mid) rangemodify(k + k, l, mid, ql, qr, w);
    if (qr > mid) rangemodify(k + k + 1, mid + 1, r, ql, qr, w);
    pushup(k);
}
int rangesum(int k, int l, int r, int ql, int qr) {
    if (l >= ql && r <= qr) return tr[k].sum;
    pushdown(k);
    int mid = l + r >> 1;
    int res = 0;
    if (ql <= mid) res += rangesum(k + k, l, mid, ql, qr), res %= mod;
    if (qr > mid) res += rangesum(k + k + 1, mid + 1, r, ql, qr), res %= mod;
    return res;
}
void solve() {
    sieve(110);
    for (int i = 1; i <= 100; i ++) {
        int x = i;
        for (auto p : primes) {
            if (i < p) continue;
            while (x % p == 0) {
                x /= p;
                fac[i].emplace_back(p);
            }
        }
        if (x > 1) fac[i].emplace_back(x);
    }

    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) {
        cin >> a[i];
    }
    build(1, 1, n);

    while (m --) {
        int op;
        cin >> op;
        if (op) {
            int l, r;
            cin >> l >> r;
            cout << rangesum(1, 1, n, l, r) << "\n";
        } else {
            int l, r, w;
            cin >> l >> r >> w;
            for (auto x : fac[w]) {
                rangemodify(1, 1, n, l, r, x);
            }
        }   
    }
}
signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t;
    t = 1;
    // std::cin >> t;

    while (t--) {
        solve();
    }

    return 0;
}

标签:Function,phi,int,sum,tr,ICPC,2021,mul,ql
From: https://www.cnblogs.com/jujujujuluo/p/18306089

相关文章

  • python 解题 洛谷B2021到B2025
    B2021输出保留3位小数的浮点数n=float(input())n=n-0.000000000000001print('%.3f'%n)B2022输出保留12位小数的浮点数m=float(input())print('%.12f'%m)B2023空格分隔输出a=input()b=int(input())c=float(input())d=float(input())print(a,"",b,"......
  • LeViT:Facebook提出推理优化的混合ViT主干网络 | ICCV 2021
    论文提出了用于快速图像分类推理的混合神经网络LeVIT,在不同的硬件平台上进行不同的效率衡量标准的测试。总体而言,LeViT在速度/准确性权衡方面明显优于现有的卷积神经网络和ViT,比如在80%的ImageNettop-1精度下,LeViT在CPU上比EfficientNet快5倍来源:晓飞的算法工程笔记公众号论......
  • 助力智慧交通,基于YOLO家族最新端到端实时目标检测算法YOLOv10全系列【n/s/m/b/l/x】参
    交通标志检测是交通标志识别系统中的一项重要任务。与其他国家的交通标志相比,中国的交通标志有其独特的特点。卷积神经网络(CNN)在计算机视觉任务中取得了突破性进展,在交通标志分类方面取得了巨大的成功。CCTSDB数据集是由长沙理工大学的相关学者及团队制作而成的,其有交通标志样......
  • The 2022 ICPC Asia Shenyang Regional Contest
    Preface本来以为今天有多校的,但到了机房发现并没有,索性就随便找了场比赛VP了然后经典开场三线红温,签了3个题后徐神被一个string关住了(后面发现他犯了个极其弱智的错误导致坐牢一整场),祁神被构造F关了,然后我写A的分类讨论写的很红温中间排名一度经典俯冲铁牌区,但好在最后......
  • Project2007-2021安装包分享:附网盘地址+安装步骤
    不得不承认,Project是从事项目管理人员最常用的软件之一,它不仅可以提高项目的效率,缩短项目开发周期,操作难度相对来说也比较小。也可以说,Project是一款专注于项目管理的桌面应用软件。它可以帮助用户制定项目计划、分派任务、管理资源、跟踪进度以及生成汇报等。MicrosoftProj......
  • 【题解】 [CSP-J 2021 T1] 分糖果
    题目描述题目大意给定正整数\(n\)、\(L\)、\(R\),求\(\max_{i\in\left[L,R\right]}{i\bmodn}\)。思路题目主要考察:分类讨论。众所周知,对于\(\forallx\),有$(x\bmodn)\in\left[0,n-1\right]$。可以分为两种情况讨论:如果\(\left\lfloor\frac{L......
  • Azure Function 时区设置
    一,引言AzureFunction上的默认使用UTC运行程序,我们在获取时间,或者通过时间执行某些逻辑时,返回UTC时间,导致业务数据不正常,由于AzureFunction是微软提供的IaaS托管服务,我们无法登录服务器来修改时区,那么我们今天将来实践操作,如何通过配置达到更改AzureFunction时区......
  • [CSP-S 2021] 廊桥分配
    戳我跳转题面题意一共有n个廊桥,全部分配给互相独立的两组。第一组有$m1$个区间$[l_i,r_i]$,第二组有$m2$个区间$[a_i,b_i]$(互相独立),一旦有廊桥空着,就会将$i$区间覆盖于总区间。问一共能满足多少个区间。思路45pts由于两组的处理方法几乎一样,在这里只举第一组的例......
  • 2021杭电多校10 D.Pty hates prime numbers题解
    前言暑期第三次组队赛是选的21年杭电多校10,遗憾爆0,被对面队打爆,赛后狠狠补题。这道题的题解,以及网上搜到的其他题解看了好久没看懂,在问了队里大腿多次后,总算磨出来了,这里讲一下我的理解。题意多次询问,每次给定\(n\)和\(k\),如果一个数的质因数里包括前\(k\)个质数,则这个数......
  • [CF1538F] Interesting Function 的题解
    题目大意给定两个正整数\(l,r\),将\(l\)不断加\(1\)直到\(l=r\),求出这一过程中\(l\)发生变化的位数总数。\(1\lel<r\le10^9\)。思路假设从\(l\)处理到\(r\)变化的次数为\(f(l,r)\)。因为直接求解出\(f(l,r)\)十分困难,所以可以通过求出\(f(0,l)\)......