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$ 首先要知 ...
随机推荐
- 【转帖】Linux命令行操作json神器jq
Linux命令行操作json神器jq https://www.cnblogs.com/chenqionghe/p/11736942.html jq类似一个awk或grep一样的神器,可以方便地在命令行 ...
- [转帖]Zookeeper
Zookeeper https://www.cnblogs.com/zhang-qc/p/8877082.html Zookeeper其实是一种为分布式应用所设计的高可用.高性能且一致的开源协调服 ...
- threading.local和高级
threading.local特点 ①为每个线程开辟空间,让你进行存取值(根据线程ID来固定某个值) ②flask中没有threading.local,但是flask中的上下文管理的思想是借鉴的thr ...
- 异常处理和UDP Socket套接字
一.异常处理 1.什么是异常处理: 程序在运行过程中出现了不可预知的错误,并且该错误没有对应的处理机制,那么就会以异常的形式表达出来,造成的影响就是整个程序无法再正常进行. 2.异常的结构: 1.异常 ...
- JAVA知识点总结篇(三)
抽象类 使用规则 abstract定义抽象类: abstract定义抽象方法,只有声明,不需要实现: 包含抽象方法的类是抽象类: 抽象类中可以包含普通方法,也可以没有抽象方法: 抽象类不能直接创建,可 ...
- 树莓派搭建python环境服务器
树莓派搭建python环境服务器 服务器结构大致为:django+uwsgi+nginx+python+sqlite 配置python环境 系统本身自带了python2.7和python3.5.在这里 ...
- nginx通过自定义header属性来转发不同的服务
一.背景 因为需要上线灰度发布,只要nginx接收到头部为: wx_unionid: 就会跳转到另外一个url,比如: 通过配置nginx 匹配请求头wx_unionid 来转发到灰度环境.核心:客户 ...
- linux 查询某个时间段的日志
目前因发生了异常大概记得发生的时间段,想查看这个时间段的日志 如我们的日志格式如下 1:09:59.946 [http-nio-12129-exec-10] INFO ntroller start = ...
- Redis读写分离(三)
1.redis高并发跟整个系统的高并发之间的关系 redis,要搞高并发的话,不可避免,要把底层的缓存搞得很好 mysql,高并发,做到了,那么也是通过一系列复杂的分库分表,订单系统,事务要求的,QP ...
- guava使用
对于Guava Cache本身就不多做介绍了,一个非常好用的本地cache lib,可以完全取代自己手动维护ConcurrentHashMap. 背景 目前需要开发一个接口I,对性能要求有非常高的要求 ...