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$ 首先要知 ...
随机推荐
- python 之 面向对象 (异常处理)
7.15 异常处理 1.什么是异常 异常是错误发生的信号,程序一旦出错,如果程序中还没有相应的处理机制,那么该错误就会产生一个异常抛出来,程序的运行也随之终止 2.一个异常分为三部分: 异常的追踪信息 ...
- python学习-30 总结
小结 1.map函数: 处理序列中的每个元素,得到结果是一个‘列表’,该‘列表’元素个数及位置与原来一样 2.filter:遍历序列中的每个元素,判断每个元素得到的布尔值,如果是True则留下来,例如 ...
- Python开发【源码剖析】 Dict对象
static void ShowDictObject(PyDictObject* dictObject) { PyDictEntry* entry = dictObject->ma_table; ...
- 用python读取word文件里的表格信息【华为云技术分享】
在企查查查询企业信息的时候,得到了一些word文件,里面有些控股企业的数据放在表格里,需要我们将其提取出来. word文件看起来很复杂,不方便进行结构化.实际上,一个word文档中大概有这么几种类型的 ...
- Win10家庭版升级到企业版的方法
一.家庭版升级企业版 1.右键单击[此电脑]——>属性 2.点击更改产品密钥 3.输入密钥:NPPR9-FWDCX-D2C8J-H872K-2YT43 4.点击下一步,验证结束后点击开始升级,然 ...
- dump net core windbg 内存分析
!dumpheap -stat //检查当前所有托管类型的统计信息 0:000> !dumpheap -stat //检查当前所有托管类型的统计信息 .... 00007ffdb9387a98 ...
- OO第三单元作业总结
OO第三单元作业总结--JML 第三单元的主题是JML规格的学习,其中的三次作业也是围绕JML规格的实现所展开的(虽然感觉作业中最难的还是如何正确适用数据结构以及如何正确地对于时间复杂度进行优化). ...
- SQL Injection (Blind)
Low级别基于布尔的盲注思路 1.判断是否存在注入,注入是字符型还是数字型 2.猜解当前数据库名 3.猜解数据库中的表名 4.猜解表中的字段名 5.猜解数据 判断是否有sql注入 输入1.1’ and ...
- 设置断点调式 fiddler
1. 用IE 打开博客园的登录界面 http://passport.cnblogs.com/login.aspx 2. 打开Fiddler, 在命令行中输入bpu http://passport. ...
- JavaScript实现网页回到顶部效果
在浏览网页时,当我们浏览到网页底部,想要立刻回到网页顶部时,这时候一般网页会提供一个回到顶部的按钮来提升用户体验,以下代码实现了该功能 HTML代码: <p id="back-top& ...