Codeforces1114F Please, another Queries on Array?
题目链接:http://codeforces.com/problemset/problem/1114/F
题意:序列$a$,有两种操作,1 区间里的数同时乘上$x$ 2 求区间的积的欧拉函数
线段树好题。
思路:最直观的思路是,线段树每个节点维护的是一个数组,表示这个数每个素因子及出现的次数,欧拉函数值用矩阵快速幂求解即可。但是这样空间不大够,而且复杂度多个常数,因此不大行。
发现300以内的素数刚好有62个,那么可以用一个long long的二进制数来表示这个数有那些素因子出现,在维护一下区间积,欧拉函数值可以用公式
$\varphi \left( n\right) =n\cdot \dfrac {\prod \left( p_{i}-1\right) }{\prod p_{i}}$
lazy_tag有两个,一个是异或,一个是乘积。我刚开始没用异或,准备直接用乘积来得到异或值,但是因为会取模,所以乘积标记不能用来得到位上的值。
#include <bits/stdc++.h>
#define lp p << 1
#define rp p << 1 | 1
#define ll long long
using namespace std; template<typename T>
inline void read(T &x) {
x = ; T f = ; char ch = getchar();
while (ch < '' || ch > '') { if (ch == '-') f = -; ch = getchar(); }
while (ch >= '' && ch <= '') { x = x * + ch - ; ch = getchar() ;}
x *= f;
} const ll MOD = 1e9 + ;
const int N = 4e5 + ;
int prime[], prin, a[N], n;
ll inv[];
bool vis[]; ll qp(ll a, ll b) {
ll res = ;
while (b) {
if (b & ) res = res * a % MOD;
a = a * a % MOD;
b >>= ;
}
return res;
} inline ll getbin(ll x) {
ll res = ;
for (int i = ; i < prin; i++)
if (x % prime[i] == ) res |= (1LL << i);
return res;
} struct SEG {
ll appear[N << ], num[N << ], lazy[N << ], lazy_bin[N << ];
void pushup(int p) {
appear[p] |= (appear[lp] | appear[rp]);
num[p] = num[lp] * num[rp] % MOD;
}
void pushdown(int p, int llen, int rlen) {
lazy[lp] = lazy[lp] * lazy[p] % MOD;
lazy[rp] = lazy[rp] * lazy[p] % MOD;
lazy_bin[lp] |= lazy_bin[p]; lazy_bin[rp] |= lazy_bin[p];
appear[lp] |= lazy_bin[lp];
appear[rp] |= lazy_bin[rp];
num[lp] = num[lp] * qp(lazy[p], llen) % MOD;
num[rp] = num[rp] * qp(lazy[p], rlen) % MOD;
lazy[p] = ;
lazy_bin[p] = ;
}
void build(int p, int l, int r) {
appear[p] = num[p] = lazy_bin[p] = ;
lazy[p] = ;
if (l == r) {
num[p] = a[l];
appear[p] = getbin(a[l]);
return;
}
int mid = l + r >> ;
build(lp, l, mid);
build(rp, mid + , r);
pushup(p);
}
void update(int p, int l, int r, int x, int y, ll v, ll bin) {
if (x <= l && r <= y) {
lazy_bin[p] |= bin;
appear[p] |= bin;
lazy[p] = lazy[p] * v % MOD;
num[p] = num[p] * qp(v, r - l + ) % MOD;
return;
}
int mid = l + r >> ;
pushdown(p, mid - l + , r - mid);
if (x <= mid) update(lp, l, mid, x, y, v, bin);
if (y > mid) update(rp, mid + , r, x, y, v, bin);
pushup(p);
}
void query(int p, int l, int r, int x, int y, ll &v, ll &bin) {
if (x <= l && r <= y) {
v = v * num[p] % MOD;
bin |= appear[p];
return;
}
int mid = l + r >> ;
pushdown(p, mid - l + , r - mid);
if (x <= mid) query(lp, l, mid, x, y, v, bin);
if (y > mid) query(rp, mid + , r, x, y, v, bin);
}
} seg; char s[]; int main() {
//freopen("in.txt", "r", stdin);
for (int i = ; i < ; i++) {
if (!vis[i]) prime[prin++] = i;
for (int j = ; j < prin && i * prime[j] < ; j++) {
vis[i * prime[j]] = ;
if (i % prime[j] == ) break;
}
}
inv[] = ;
for (int i = ; i < ; i++) inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
read(n);
int q; read(q);
for (int i = ; i <= n; i++) read(a[i]);
seg.build(, , n);
while (q--) {
scanf("%s", s);
if (s[] == 'T') {
int l, r;
read(l); read(r);
ll v = , bin = ;
seg.query(, , n, l, r, v, bin);
for (int i = ; i < prin; i++) {
if (bin >> i & ) v = v * (prime[i] - ) % MOD * inv[prime[i]] % MOD;
}
printf("%lld\n", v);
} else {
int l, r, w;
read(l); read(r); read(w);
seg.update(, , n, l, r, w, getbin(w));
}
}
return ;
}
Codeforces1114F Please, another Queries on Array?的更多相关文章
- Codeforces 1114F Please, another Queries on Array? 线段树
Please, another Queries on Array? 利用欧拉函数的计算方法, 用线段树搞一搞就好啦. #include<bits/stdc++.h> #define LL ...
- CF1114F Please, another Queries on Array?
CF1114F Please, another Queries on Array? 考虑用线段树维护取模后的区间积和真正的区间积所含有的质因子. 每次询问查得这两个值后,一乘一除,即可算出该区间积的欧 ...
- [Codeforces 266E]More Queries to Array...(线段树+二项式定理)
[Codeforces 266E]More Queries to Array...(线段树+二项式定理) 题面 维护一个长度为\(n\)的序列\(a\),\(m\)个操作 区间赋值为\(x\) 查询\ ...
- 暑假集训单切赛第一场 CF 266E More Queries to Array(线段树+二项式展开式)
比赛时,第二题就是做的这个,当时果断没仔细考虑,直接用线段树暴力求.结果易想而知,超时了. 比赛后搜了搜题解,恍然大悟. 思路:显然用线段树,但是由于每次查询都会有变,所以不可能存储题目中的式子. ...
- [Codeforces266E]More Queries to Array...——线段树
题目链接: Codeforces266E 题目大意:给出一个序列$a$,要求完成$Q$次操作,操作分为两种:1.$l,r,x$,将$[l,r]$的数都变为$x$.2.$l,r,k$,求$\sum\li ...
- Codeforces 1114F Please, another Queries on Array? [线段树,欧拉函数]
Codeforces 洛谷:咕咕咕 CF少有的大数据结构题. 思路 考虑一些欧拉函数的性质: \[ \varphi(p)=p-1\\ \varphi(p^k)=p^{k-1}\times (p-1)= ...
- 【Codeforces 1114F】Please, another Queries on Array?
Codeforces 1114 F 题意:给你一个序列\(a_{1\dots n}\),以及\(q\)次查询,每次查询有两种格式: TOTIENT \(l\) \(r\):求出\(\phi(\Pi_{ ...
- CF1114F Please, another Queries on Array?(线段树,数论,欧拉函数,状态压缩)
这题我在考场上也是想出了正解的……但是没调出来. 题目链接:CF原网 题目大意:给一个长度为 $n$ 的序列 $a$,$q$ 个操作:区间乘 $x$,求区间乘积的欧拉函数模 $10^9+7$ 的值. ...
- Please, another Queries on Array? CodeForces - 1114F (线段树,欧拉函数)
这题刚开始看成求区间$\phi$和了........先说一下区间和的做法吧...... 就是说将题目的操作2改为求$(\sum\limits_{i=l}^{r}\phi(a[i]))\%P$ 首先要知 ...
随机推荐
- 唯一ID生成器--雪花算法
在微服务架构,分布式系统中的操作会有一些全局性ID的需求,所以我们不能用数据库本身的自增功能来产生主键值,只能由程序来生成唯一的主键值.我们采用的是twitter的snokeflake(雪花)算法. ...
- python 字符串替换功能 string.replace()可以用正则表达式,更优雅
说起来不怕人笑话,我今天才发现,python 中的字符串替换操作,也就是 string.replace() 是可以用正则表达式的. 之前,我的代码写法如下,粗笨: 自从发现了正则表达式也生效后,代码变 ...
- node-red inject节点 debug节点 switch节点
inject节点: https://blog.csdn.net/geek_monkey/article/details/80737818 debug节点: https://blog.csdn.net/ ...
- java之spring之整合ssh
这篇主要讲解spring + struts2 + hibernate : 目录结构如下: t_role t_user 1.新建 web项目 :spring_ssh 2.在 WebRoot/WEB-IN ...
- Fiddler-修改请求的上行参数
方法一:对所有的请求打断点 1.rules->automatic Breakpoints->Befor Requests 2.点击选择需要修改的请求 3.选择右侧请求区域的 Inspect ...
- Vue学习之webpack调用第三方loader(十五)
---恢复内容开始--- 一.webpack 默认只能打包处理 JS 类型的文件,无法处理 其他的非 JS 类型的文件: 如果非要处理 非 JS 类型的文件,我们需要手动安装一些 合适 第三方 lo ...
- 数据分析 之 NumPy
目录 简单了解数据分析 Python数据分析三剑客(Numpy,Pandas,Matplotlib) 简单使用np.array() 使用np的routines函数创建数组 ndarray N维数组对象 ...
- PM2 对 Node 项目进行线上部署与配置
pm2 是一个带有负载均衡功能的 Node 应用的进程管理器. 1. pm2 主要特点 内建负载均衡(使用Node cluster 集群模块) 保持后台运行 进程守护,系统崩溃后自动重启 启动多进程, ...
- WPF 依赖属性前言
WPF 依赖属性前言 在.net中,我们可以属性来获取或设置字段的值,不需要在编写额外的get和set方法,但这有一个前提,那就是需要在对象中拥有一个字段,才能在此字段的基础上获取或设置字段的值, ...
- 【DATAGUARD】物理dg在主库丢失归档文件的情况下的恢复(七)
[DATAGUARD]物理dg在主库丢失归档文件的情况下的恢复(七) 一.1 BLOG文档结构图 一.2 前言部分 一.2.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到 ...