这题我在考场上也是想出了正解的……但是没调出来。

题目链接:CF原网

题目大意:给一个长度为 $n$ 的序列 $a$,$q$ 个操作:区间乘 $x$,求区间乘积的欧拉函数模 $10^9+7$ 的值。

$1\le n\le 4\times 10^5,1\le q\le 2\times 10^5,1\le a_i,x\le 300$。时限 5.5s,空限 256MB。


明显线段树。

有一个想法是维护区间积的欧拉函数,但是这样时间复杂度和代码复杂度都很高……

我的做法是维护区间积。而欧拉函数,就是看看区间中包含什么质因子,然后除一下乘一下好了。

区间积就不用说了。

包含什么质因子?难道要开bool数组吗?时间复杂度很高……

经过后台黑科技操作发现 $300$ 以内的质数只有 $62$ 个。明摆着状压的节奏!

好的,这题做完了。细节的东西在代码中都有。

对于我的代码实现来说:(以下令 $k=62$)

建树 $O(kn)$。

合并节点 $O(1)$。

下推标记 $O(\log n)$。

区间乘 $O(\log^2 n+k)$。

查询欧拉函数 $O(\log n+k)$。

总时间复杂度应该是 $O((n+q)k+q\log^2n)$。其实跑得不慢,我跑得最慢的点是1934ms。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=,mod=;
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
char ch=getchar();int x=,f=;
while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return f?-x:x;
}
int n,q,pri[],pl,a[maxn],inv[],f[],tag1[maxn*]; //tag1表示区间要乘多少
ll tag2[maxn*]; //tag2表示区间会多出哪些质因子(也是压缩过的)
//为什么要两个标记呢?不能直接对tag1分解质因子吗?
//因为tag1乘几遍就会被取模,这样看起来质因子就变了。所以额外加一个tag2表示真的质因子集合。
bool vis[];
void init(){
FOR(i,,){
if(!vis[i]) pri[++pl]=i;
for(int j=;j<=pl && i*pri[j]<=;j++){
vis[i*pri[j]]=true;
if(i%pri[j]==) break;
}
}
inv[]=;
FOR(i,,) inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod;
FOR(i,,pl) f[i]=1ll*inv[pri[i]]*(pri[i]-)%mod;
//f[i]表示除以p[i],再乘上p[i]-1,便于计算欧拉函数
}
inline int qpow(int a,int b){
int ans=;
for(;b;b>>=,a=1ll*a*a%mod) if(b&) ans=1ll*ans*a%mod;
return ans;
}
struct node{
int pro;ll has;
}nd[maxn*]; //一个线段树节点,pro是区间积,has是区间包含哪些质因子(压缩过的)
void pushup(node &o,node l,node r){ //合并
o.has=l.has|r.has; //直接取或
o.pro=1ll*l.pro*r.pro%mod;
}
void setmult(int o,int l,int r,int x,ll y){ //对第o个节点(管辖[l,r])区间乘x,质因子多了y
tag1[o]=1ll*tag1[o]*x%mod;
tag2[o]|=y;
nd[o].pro=1ll*nd[o].pro*qpow(x,r-l+)%mod; //记得乘r-l+1次方
nd[o].has|=y;
}
void pushdown(int o,int l,int r){ //下传标记
if(!tag2[o]) return;
int mid=(l+r)>>;
setmult(lson,tag1[o],tag2[o]);
setmult(rson,tag1[o],tag2[o]);
tag1[o]=;tag2[o]=; //记得tag1闲置时是1
}
void build(int o,int l,int r){
tag1[o]=;tag2[o]=;
if(l==r){
nd[o].pro=a[l];
FOR(i,,pl) //记录质因子集合
if(a[l]%pri[i]==) nd[o].has|=1ll<<(i-);
return;
}
int mid=(l+r)>>;
build(lson);build(rson);
pushup(nd[o],nd[o<<],nd[o<<|]);
}
void mult(int o,int l,int r,int ql,int qr,int x,ll y){ //外面调用时先把质因子集合弄好,会省时间
if(l>=ql && r<=qr){
setmult(o,l,r,x,y); //直接设上
return;
}
pushdown(o,l,r);
int mid=(l+r)>>;
if(mid>=ql) mult(lson,ql,qr,x,y);
if(mid<qr) mult(rson,ql,qr,x,y);
pushup(nd[o],nd[o<<],nd[o<<|]);
}
node query(int o,int l,int r,int ql,int qr){
if(l>=ql && r<=qr) return nd[o];
pushdown(o,l,r);
int mid=(l+r)>>;
if(mid<ql) return query(rson,ql,qr);
if(mid>=qr) return query(lson,ql,qr);
node ans;
pushup(ans,query(lson,ql,qr),query(rson,ql,qr)); //合并两边
return ans;
}
int main(){
init();
n=read();q=read();
FOR(i,,n) a[i]=read();
build(,,n);
FOR(i,,q){
char op[];
scanf("%s",op);
int l=read(),r=read();
if(op[]=='M'){ //乘操作
int x=read();ll y=;
FOR(i,,pl) if(x%pri[i]==) y|=1ll<<(i-); //先处理质因子集合
mult(,,n,l,r,x,y);
}
else{ //求欧拉函数操作
node ans=query(,,n,l,r);
int s=ans.pro; //区间积
FOR(i,,pl) if(ans.has&(1ll<<(i-))) s=1ll*s*f[i]%mod; //区间含有第i个质数,那就要除以p[i],再乘上p[i]-1
printf("%d\n",s);
}
}
}

CF1114F Please, another Queries on Array?(线段树,数论,欧拉函数,状态压缩)的更多相关文章

  1. Codeforces 1114F Please, another Queries on Array? [线段树,欧拉函数]

    Codeforces 洛谷:咕咕咕 CF少有的大数据结构题. 思路 考虑一些欧拉函数的性质: \[ \varphi(p)=p-1\\ \varphi(p^k)=p^{k-1}\times (p-1)= ...

  2. BZOJ 4026 dC Loves Number Theory (主席树+数论+欧拉函数)

    题目大意:给你一个序列,求出指定区间的(l<=i<=r) mod 1000777 的值 还复习了欧拉函数以及线性筛逆元 考虑欧拉函数的的性质,(l<=i<=r),等价于 (p[ ...

  3. [Codeforces 266E]More Queries to Array...(线段树+二项式定理)

    [Codeforces 266E]More Queries to Array...(线段树+二项式定理) 题面 维护一个长度为\(n\)的序列\(a\),\(m\)个操作 区间赋值为\(x\) 查询\ ...

  4. Codeforces 1114F Please, another Queries on Array? 线段树

    Please, another Queries on Array? 利用欧拉函数的计算方法, 用线段树搞一搞就好啦. #include<bits/stdc++.h> #define LL ...

  5. 暑假集训单切赛第一场 CF 266E More Queries to Array(线段树+二项式展开式)

    比赛时,第二题就是做的这个,当时果断没仔细考虑,直接用线段树暴力求.结果易想而知,超时了. 比赛后搜了搜题解,恍然大悟. 思路:显然用线段树,但是由于每次查询都会有变,所以不可能存储题目中的式子.   ...

  6. [Codeforces266E]More Queries to Array...——线段树

    题目链接: Codeforces266E 题目大意:给出一个序列$a$,要求完成$Q$次操作,操作分为两种:1.$l,r,x$,将$[l,r]$的数都变为$x$.2.$l,r,k$,求$\sum\li ...

  7. CF383C Propagating tree (线段树,欧拉序)

    \(tag\)没开够\(WA\)了一发... 求出\(dfs\)序,然后按深度分类更新与查询. #include <iostream> #include <cstdio> #i ...

  8. Please, another Queries on Array?(Codeforces Round #538 (Div. 2)F+线段树+欧拉函数+bitset)

    题目链接 传送门 题面 思路 设\(x=\prod\limits_{i=l}^{r}a_i\)=\(\prod\limits_{i=1}^{n}p_i^{c_i}\) 由欧拉函数是积性函数得: \[ ...

  9. CF1114F Please, another Queries on Array?

    CF1114F Please, another Queries on Array? 考虑用线段树维护取模后的区间积和真正的区间积所含有的质因子. 每次询问查得这两个值后,一乘一除,即可算出该区间积的欧 ...

随机推荐

  1. [译]React 在服务端渲染的实现

    原文地址:Server-Side React Rendering 原文作者:Roger Jin React 在服务端渲染的实现 React是最受欢迎的客户端 JavaScript 框架,但你知道吗(可 ...

  2. CSS 分类 (Classification) 实例

    CSS 分类 (Classification) 实例CSS 分类属性 (Classification)CSS 分类属性允许你控制如何显示元素,设置图像显示于另一元素中的何处,相对于其正常位置来定位元素 ...

  3. MySQL高可用架构-MMM环境部署记录

    MMM介绍MMM(Master-Master replication manager for MySQL)是一套支持双主故障切换和双主日常管理的脚本程序.MMM使用Perl语言开发,主要用来监控和管理 ...

  4. Python-str-操作-6

    #字符串的索引与切片 s = 'ABCDLSESRF' #索引 s1 = s[0] print(s1) s2 = s[2] print(s2) s3 = s[-1] print(s3) s4 = s[ ...

  5. Leetcode——32.最长有效括号【##】

    @author: ZZQ @software: PyCharm @file: leetcode32_最长有效括号.py @time: 2018/11/22 19:19 要求:给定一个只包含 '(' 和 ...

  6. The Last Reader Response——13-17

    Hi, everybody, nice to meet you, this is probably my best and meet you at a time, in the past a seme ...

  7. 【评分】Alpha阶段

    [评分]Alpha阶段 总结 按时交 - 有分 晚交 - 0分 迟交一周以上 - 倒扣本次作业分数 抄袭 - 倒扣本次作业分数 请大家回忆一下第一次作业的总结:http://www.cnblogs.c ...

  8. [转] Linux有问必答:如何修复“sshd error: could not load host key”

    编译自:http://ask.xmodulo.com/sshd-error-could-not-load-host-key.html作者: GOLinux 本文地址:https://linux.cn/ ...

  9. Caffe2的安装

    源码下载 首先下载caffe2的源码:https://github.com/caffe2/caffe2 网上都建议使用git命令下载,因为caffe2依赖了很多第三方模块,git会根据依赖自动下载第三 ...

  10. 毕业设计心得与整理-APP-主题切换

    1.定义主体颜色: 在style自定义了三个属性: <item name="textLight">@android:color/white</item> & ...