CF1114F Please, another Queries on Array?(线段树,数论,欧拉函数,状态压缩)
这题我在考场上也是想出了正解的……但是没调出来。
题目链接: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?(线段树,数论,欧拉函数,状态压缩)的更多相关文章
- Codeforces 1114F Please, another Queries on Array? [线段树,欧拉函数]
Codeforces 洛谷:咕咕咕 CF少有的大数据结构题. 思路 考虑一些欧拉函数的性质: \[ \varphi(p)=p-1\\ \varphi(p^k)=p^{k-1}\times (p-1)= ...
- BZOJ 4026 dC Loves Number Theory (主席树+数论+欧拉函数)
题目大意:给你一个序列,求出指定区间的(l<=i<=r) mod 1000777 的值 还复习了欧拉函数以及线性筛逆元 考虑欧拉函数的的性质,(l<=i<=r),等价于 (p[ ...
- [Codeforces 266E]More Queries to Array...(线段树+二项式定理)
[Codeforces 266E]More Queries to Array...(线段树+二项式定理) 题面 维护一个长度为\(n\)的序列\(a\),\(m\)个操作 区间赋值为\(x\) 查询\ ...
- Codeforces 1114F Please, another Queries on Array? 线段树
Please, another Queries on Array? 利用欧拉函数的计算方法, 用线段树搞一搞就好啦. #include<bits/stdc++.h> #define LL ...
- 暑假集训单切赛第一场 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 ...
- CF383C Propagating tree (线段树,欧拉序)
\(tag\)没开够\(WA\)了一发... 求出\(dfs\)序,然后按深度分类更新与查询. #include <iostream> #include <cstdio> #i ...
- 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}\) 由欧拉函数是积性函数得: \[ ...
- CF1114F Please, another Queries on Array?
CF1114F Please, another Queries on Array? 考虑用线段树维护取模后的区间积和真正的区间积所含有的质因子. 每次询问查得这两个值后,一乘一除,即可算出该区间积的欧 ...
随机推荐
- python语言程序设计9
1, 数字转换形式中有很多东西都不会,但是总不能放仍不管把? 总结点东西吧,比如 print()中增加end=""参数表示输入后不增加换行,多个print可以连续输出. 2, 我还 ...
- CSS 分类 (Classification) 实例
CSS 分类 (Classification) 实例CSS 分类属性 (Classification)CSS 分类属性允许你控制如何显示元素,设置图像显示于另一元素中的何处,相对于其正常位置来定位元素 ...
- Ionic 1 & 2 开发常见问题 Q&A
原文发表于我的技术博客 本文分享了在 Ionic 1 & 2 版本开发过程中常见问题的一些 Q&A,供慕课网同学或其他朋友参考. 原文发表于我的技术博客 1. 版本的问题 Ionic ...
- Jmeter(GUI模式)教程
前些天,领导让我做接口的压力测试.What??我从未接触过这方面,什么都不知道,一脸蒙.于是我从学习jmeter开始入手. 现在记录下来jmeter的使用步骤,希望能对大家有所帮助. 一.安装Jmet ...
- 几何学观止(Riemann流形部分)
上承这个页面,相较之前,增加了古典的曲线曲面论,这部分介绍得很扼要,Riemann流形介绍得也很快,花了仅仅30页就介绍到了Gauss-Bonnet公式.同时配上了提示完整的习题. 几何学观止-Rie ...
- C_数据结构_循环队列
# include <stdio.h> # include <malloc.h> typedef struct Queue { int * pBase; int front; ...
- alpa开发阶段团队贡献分
这是我们团队之前决定的分配方式: 1.凡是认真完成自己任务的队员,都将有基础分30分(态度分). 2. 将整个项目细化为不同的任务,列出一个任务清单,在综合.协调完每名成员的意愿后,我会分配清单中的任 ...
- Linux内核分析第八周总结
第八章 进程的切换和系统的一般执行过程 进程调度与进程调度的时机分析 第一种分类: I/O密集型(I/O-bound):频繁的进行I/O,通常会花费很多时间等待I/O操作的完成 CPU密集型(CPU- ...
- 小学四则运算APP 第二个冲刺 第一天
团队成员:陈淑筠.杨家安.陈曦 团队选题:小学四则运算APP 第二次冲刺阶段时间:11.29~12.09 本次发布的是已完成的功能二(选择题): ChoiceActivity.java: packag ...
- 学习yii2.0——基础入门
声明:本文内容来自于yiichina.com的权威指南. 安装 推荐使用composer来安全,可能有点慢(要下载的依赖比较多). composer create-project --prefer-d ...