Codeforces 1114F(欧拉函数、线段树)
要点
- 欧拉函数对于素数有一些性质,考虑将输入数据唯一分解后进行素数下的处理。
- 对于素数\(p\)有:\(\phi(p^k)=p^{k-1}*(p-1)=p^k*\frac{p-1}{p}\),因此将\(a_i\)唯一分解后有:\(\phi(\prod_{i=l}^ra_i)=\prod_{i=l}^ra_i*\prod_{p\ \in P}\frac{p-1}{p}\),其中\(P\)是\([l,r]\)内的\(a_i\)分解后的素数集合。
- 这样转化公式以后,就只需线段树维护一下区间乘积和区间是否有某素数即可,第二个维护可以使用bitset二进制串代表有没有。
- \(a_i\)和\(x\)都很小,可以预处理1~300范围内的所需数据。
const int maxn = 4e5 + 5, mod = 1e9 + 7;
int n, q;
bst Mask[305];//bitset
vector<int> primes, invp;
int ksm(int a, int b) {
int res = 1;
for (; b; b >>= 1) {
if (b & 1) res = (ll)res * a % mod;
a = (ll)a * a % mod;
}
return res;
}
void pre(int n) {
bool vis[305] = {false};
for (int i = 2; i <= n; i++) {
if (!vis[i]) {
primes.push_back(i);
invp.push_back(ksm(i, mod - 2));
for (int j = i * i; j <= n; j += i) {
vis[j] = true;
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 0; j < primes.size(); j++) {
if (i % primes[j] == 0) {
Mask[i][j] = 1;
}
}
}
}
class SegmentTree {
public:
#define ls(p) p << 1
#define rs(p) p << 1 | 1
struct Node {
int l, r, mul, tag;
bst bits, laz;
}t[maxn * 3];
void Push_up(int p) {
t[p].mul = (ll)t[ls(p)].mul * t[rs(p)].mul % mod;
t[p].bits = t[ls(p)].bits | t[rs(p)].bits;
t[p].tag = 1;
t[p].laz.reset();
}
void Deal(int son, int fa) {
t[son].mul = (ll)t[son].mul * ksm(t[fa].tag, t[son].r - t[son].l + 1) % mod;
t[son].bits |= t[fa].laz;
t[son].tag = (ll)t[son].tag * t[fa].tag % mod;
t[son].laz |= t[fa].laz;
}
void Push_down(int p) {
if (t[p].tag != 1 || t[p].laz.any()) {
Deal(ls(p), p), Deal(rs(p), p);
t[p].tag = 1, t[p].laz.reset();
}
}
void Build(int l, int r, int p) {
t[p].l = l, t[p].r = r;
if (l == r) {
cin >> t[p].mul;
t[p].tag = 1;
t[p].bits = Mask[t[p].mul];
t[p].laz.reset();
return;
}
int mid = (l + r) >> 1;
Build(l, mid, ls(p));
Build(mid + 1, r, rs(p));
Push_up(p);
}
void Modify(int l, int r, int p, int x) {
if (l <= t[p].l && t[p].r <= r) {
t[p].mul = (ll)t[p].mul * ksm(x, t[p].r - t[p].l + 1) % mod;
t[p].tag = (ll)t[p].tag * x % mod;
t[p].bits |= Mask[x];
t[p].laz |= Mask[x];
return;
}
Push_down(p);
int mid = (t[p].l + t[p].r) >> 1;
if (l <= mid) Modify(l, r, ls(p), x);
if (mid < r) Modify(l, r, rs(p), x);
Push_up(p);
}
friend Node operator + (const Node &A, const Node &B) {
Node tmp;
tmp.mul = (ll)A.mul * B.mul % mod;
tmp.bits = A.bits | B.bits;
return tmp;
}
Node Query(int l, int r, int p) {
if (l <= t[p].l && t[p].r <= r)
return t[p];
Push_down(p);
int mid = (t[p].l + t[p].r) >> 1;
if (mid >= r) return Query(l, r, ls(p));
if (l > mid) return Query(l, r, rs(p));
return Query(l, r, ls(p)) + Query(l, r, rs(p));
}
}T;
int main() {
ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
pre(300);
cin >> n >> q;
T.Build(1, n, 1);
while (q--) {
string s;
int l, r, x;
cin >> s >> l >> r;
if (s == "MULTIPLY") {
cin >> x;
T.Modify(l, r, 1, x);
} else {
auto res = T.Query(l, r, 1);
int ans = res.mul;
for (int j = 0; j < primes.size(); j++) {
if (res.bits[j]) {
ans = (ll)ans * (primes[j] - 1) % mod * invp[j] % mod;
}
}
cout << ans << '\n';
}
}
return 0;
}
Codeforces 1114F(欧拉函数、线段树)的更多相关文章
- LightOJ 1370 Bi-shoe and Phi-shoe 欧拉函数+线段树
分析:对于每个数,找到欧拉函数值大于它的,且标号最小的,预处理欧拉函数,然后按值建线段树就可以了 #include <iostream> #include <stdio.h> ...
- loj1370(欧拉函数+线段树)
传送门:Bi-shoe and Phi-shoe 题意:给出多个n(1<=n<=1e6),求满足phi(x)>=n的最小的x之和. 分析:先预处理出1~1e6的欧拉函数,然后建立一颗 ...
- [BZOJ4026]dC Loves Number Theory 欧拉函数+线段树
链接 题意:给定长度为 \(n\) 的序列 A,每次求区间 \([l,r]\) 的乘积的欧拉函数 题解 考虑离线怎么搞,将询问按右端点排序,然后按顺序扫这个序列 对于每个 \(A_i\) ,枚举它的质 ...
- LOJ #2142. 「SHOI2017」相逢是问候(欧拉函数 + 线段树)
题意 给出一个长度为 \(n\) 的序列 \(\{a_i\}\) 以及一个数 \(p\) ,现在有 \(m\) 次操作,每次操作将 \([l, r]\) 区间内的 \(a_i\) 变成 \(c^{a_ ...
- bzoj4869: [Shoi2017]相逢是问候(欧拉函数+线段树)
这题是六省联考的...据说数据还出了点锅,心疼六省选手QAQ 首先要知道扩展欧拉定理... 可以发现每次区间操作都会使模数进行一次phi操作,而一个数最多取logp次phi就会变成1,这时后面的指数就 ...
- [LNOI] 相逢是问候 || 扩展欧拉函数+线段树
原题为2017六省联考的D1T3 给出一个序列,m次操作,模数p和参数c 操作分为两种: 1.将[l,r]区间内的每个数x变为\(c^x\) 2.求[l,r]区间内数的和%p 首先,我们要了解一些数论 ...
- BZOJ 4034 树上操作(树的欧拉序列+线段树)
刷个清新的数据结构题爽一爽? 题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x ...
- BZOJ 4034 [HAOI2015]树上操作(欧拉序+线段树)
题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...
- BZOJ 4034: [HAOI2015]树上操作 [欧拉序列 线段树]
题意: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有点的点权和. 显然树链剖分可做 ...
随机推荐
- str_2.判断两个字符串是否互为旋转词
1. 字符串str的前面任意部分挪到后面形成的字符串叫做字符串str的旋转词 $str1 = "2ab1"; $str2 = "ab12"; $ret = is ...
- 64位 Windows 用了 32位编译平台 编译不过 MySQL API
发生在一周前的事情了,当时想感受下 MySQL C API ,就写了几个小例子.虽然是在 Windows(我的工作电脑是 64位 Windows) 上面,但是不想用 VS ,只想用文本软件写好代码后用 ...
- properties文件的解析
此文章是从网上看到一篇实用小文章,感觉不过,摘录下来的!如有问题,可及时联系,可立刻做相应处理! Java读取.properties 配置文件的几种方法 在做java工程时, 经常会将一些配置信息放到 ...
- MySQL当月负毛利订单明细_20161027
#当月每天负毛利订单明细 SELECT c.ID,a.city AS 城市,a.username AS 用户ID,a.订单日期,a.订单号,a.销售确认额,a.成本额,a.毛利1, CASE THEN ...
- 「UVA1636」Headshot(概率
题意翻译 你有一把枪(左轮的),你随机装了一些子弹,你开了一枪,发现没有子弹,你希望下一枪也没有子弹,你是应该直接开一枪(输出"SHOOT"),还是先转一下,再开一枪(输出&quo ...
- 「BZOJ2721」「LuoguP1445」 [Violet]樱花(数论
题目背景 我很愤怒 题目描述 求方程 $\frac{1}{x}+\frac{1}{y}=\frac{1}{N!}$ 的正整数解的组数,其中$N≤10^6$. 解的组数,应模$1e9+7$. 输入输出格 ...
- 打开关闭tomcat的目录浏览功能
目录浏览功能 conf/web.xml中init-param中有对于listing的定义,设置为true即可实现tomcat的目录浏览: tomcat的管理用户设置 conf/tomcat-users ...
- python--面向对象(最全讲解)
http://www.cnblogs.com/Eva-J/articles/7293890.html 阅读目录 楔子 面向过程vs面向对象 初识面向对象 类的相关知识 对象的相关知识 对象之间的交互 ...
- SVN服务器搭建教程
常见的源代码管理工具 CVS 历史悠久,现在几乎没人使用 SVN 集中式版本控制的代表 CVS的接班人,速度比CVS快,功能比CVS强大 在国内使用率非常高(70%~90%) GIT 分布式源代码管理 ...
- JSP+JavaBean+Servlet工作原理实例…
JSP+JavaBean+Servlet工作原理实例讲解 首先,JavaBean和Servlet虽都是Java程序,但是是完全不同的两个概念.引用mz3226960提出的MVC的概念,即M-model ...