CF1114F Please, another Queries on Array?

  • 考虑用线段树维护取模后的区间积和真正的区间积所含有的质因子.
  • 每次询问查得这两个值后,一乘一除,即可算出该区间积的欧拉函数.
  • 区间积容易维护,主要考虑如何维护所含的质因子.
  • 注意到 \(a_i\) 和每次乘的 \(x\) 都 \(\leq 300\) , 而 \(300\) 以内的质数恰有 \(62\) 个,所以可以用一个 \(62\) 位的非负整数状压表示一个区间所含的质因子,用 \(long\ long\) 恰能存下.
  • 注意用 \(long\ long\) 状压时需写成 \(1LL<<k\) .
  • 此题难点在于想到分别维护区间积和质因子,以及用状压记录质因子.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pii pair<int,int>
inline int read()
{
int x=0;
bool pos=1;
char ch=getchar();
for(;!isdigit(ch);ch=getchar())
if(ch=='-')
pos=0;
for(;isdigit(ch);ch=getchar())
x=x*10+ch-'0';
return pos?x:-x;
}
const int MAXN=4e5+10;
int prime[MAXN]={2,3,5,7,11,13,17,19,23,29,31,37,41,
43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,
127,131,137,139,149,151,157,163,167,173,179,181,191,193,
197,199,211,223,227,229,233,239,241,251,257,263,269,271,
277,281,283,293};
const int siz=62;
const int P=1e9+7;
int a[MAXN];
inline int add(int a,int b)
{
return (a + b) % P;
}
inline int mul(int a,int b)
{
return 1LL * a * b % P;
}
int fpow(int a,int b)
{
int res=1;
while(b)
{
if(b&1)
res=mul(res,a);
a=mul(a,a);
b>>=1;
}
return res;
}
int inv(int x)
{
return fpow(x,P-2);
}
#define root Tree[o]
#define lson Tree[o<<1]
#define rson Tree[o<<1|1]
ll calcdiv(ll x)
{
ll res=0;
for(ll i=0;i<siz;++i)
if(x%prime[i]==0)
res|=(1LL<<i);
return res;
}
struct node{
int l,r;
ll div,prod;
int tag1;
ll tag2;
node()
{
div=0;
prod=1;
tag1=1;
tag2=0;
}
}Tree[MAXN<<2];
void pushup(int o)
{
root.prod=mul(lson.prod,rson.prod);
root.div=lson.div|rson.div;
}
void BuildTree(int o,int l,int r)
{
root.l=l,root.r=r;
if(l==r)
{
root.prod=a[l];
root.div=calcdiv(a[l]);
return;
}
int mid=(l+r)>>1;
BuildTree(o<<1,l,mid);
BuildTree(o<<1|1,mid+1,r);
pushup(o);
}
void Modifiy(int o,int v,ll div)
{
root.tag1=mul(root.tag1,v);
root.tag2|=div;
root.prod=mul(root.prod,fpow(v,root.r-root.l+1));
root.div|=div;
}
void pushdown(int o)
{
if(root.tag2==0)
return;
Modifiy(o<<1,root.tag1,root.tag2);
Modifiy(o<<1|1,root.tag1,root.tag2);
root.tag1=1;
root.tag2=0;
}
void update(int o,int L,int R,int v,ll div)
{
int l=root.l,r=root.r;
if(l>R || r<L)
return;
if(L<=l && r<=R)
{
Modifiy(o,v,div);
return;
}
int mid=(l+r)>>1;
pushdown(o);//修改时也要下传标记
if(L<=mid)
update(o<<1,L,R,v,div);
if(R>mid)
update(o<<1|1,L,R,v,div);
pushup(o);
}
int query(int o,int L,int R,ll &totdiv)
{
int l=root.l,r=root.r;
int res=1;
if(l>R || r<L)
return res;
if(L<=l && r<=R)
{
totdiv|=root.div;
return root.prod;
}
int mid=(l+r)>>1;
pushdown(o);
if(L<=mid)
res=mul(res,query(o<<1,L,R,totdiv));
if(R>mid)
res=mul(res,query(o<<1|1,L,R,totdiv));
return res;
}
int n,m;
int main()
{
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout);
n=read();
m=read();
for(int i=1;i<=n;++i)
a[i]=read();
BuildTree(1,1,n);
for(int p=1;p<=m;++p)
{
char buf[10];
scanf("%s",buf);
if(buf[0]=='M')
{
int l=read(),r=read(),x=read();
ll div=calcdiv(x);
update(1,l,r,x,div);
}
else
{
assert(buf[0]=='T');
int l=read(),r=read();
ll div=0;
int prod=query(1,l,r,div);
for(ll i=0;i<siz;++i)
{
if((div>>i)&1LL)
prod=mul(prod,prime[i]-1),prod=mul(prod,inv(prime[i]));
}
printf("%d\n",prod);
}
}
return 0;
}

CF1114F Please, another Queries on Array?的更多相关文章

  1. CF1114F Please, another Queries on Array?(线段树,数论,欧拉函数,状态压缩)

    这题我在考场上也是想出了正解的……但是没调出来. 题目链接:CF原网 题目大意:给一个长度为 $n$ 的序列 $a$,$q$ 个操作:区间乘 $x$,求区间乘积的欧拉函数模 $10^9+7$ 的值. ...

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

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

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

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

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

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

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

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

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

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

  7. 【Codeforces 1114F】Please, another Queries on Array?

    Codeforces 1114 F 题意:给你一个序列\(a_{1\dots n}\),以及\(q\)次查询,每次查询有两种格式: TOTIENT \(l\) \(r\):求出\(\phi(\Pi_{ ...

  8. Please, another Queries on Array? CodeForces - 1114F (线段树,欧拉函数)

    这题刚开始看成求区间$\phi$和了........先说一下区间和的做法吧...... 就是说将题目的操作2改为求$(\sum\limits_{i=l}^{r}\phi(a[i]))\%P$ 首先要知 ...

  9. CodeForces 266E More Queries to Array...(线段树+式子展开)

    开始觉得是规律题的,自以为是的推了一个规律,结果测试数据都没过....看了love神的博客才发现只是把式子展开就找到规律了.不过挺6的是我虽然想错了,但是维护的的东西没有错,只是改改(改了进两个小时好 ...

随机推荐

  1. 秒懂算法1——冒泡排序,及一种小改进(C#实现)

    算法思路: 重复走访每两个相邻元素,比较大小交换位置,直至排序完成. 有兴趣电话可以看一下这个[冒泡排序踢踏舞]的视频,很形象的演示了排序过程,额呵呵~~ 性质: 冒泡排序是一种原地排序(只有常数个元 ...

  2. GridControl 史上最全的资料(二)

    GridControl详解(四)分组排序汇总 分组: 按时间分第一组: 按性别分第二组: 显示结果: 高级设置: 将所有组展开代码:gridView1.ExpandAllGroups(); 显示结果: ...

  3. keepalived与nginx安装

    目的: 当用户请求访问时,会通过nginx来访问web服务应用,因此我们必须要保证nginx的高可用,要保证nginx的高可用,我们需要通过keepalived来监控nginx,并对外提供1个虚拟的v ...

  4. 前端构建大法 Gulp 系列

    参考: 前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gulp ...

  5. spring mvc: 生成RSS源

    spring mvc: 生成RSS源 准备: 从相同的maven存储库页面下载 Rome 库及其依赖项rome-utils,jdom和slf4j.和所需的依赖关系 <!-- rss源依赖 --& ...

  6. 备注Quartz触发器设置

    corn表达式时间格式: <!-- s m h d m w(?) y(?) -->, 分别对应: 秒>分>小时>日>月>周>年, ●星号(*):可用在所 ...

  7. C# 获取命名空间对应的程序集位置

    由于同名命名空间会被多个程序集使用,C#没有提供直接的方法(对象浏览器也不行)通过命名空间获得程序集位置,这样就不方便找到那些引用文件时什么. 那么可以在立即窗口,中断某个代码的时候,去查询类所在程序 ...

  8. 1.SpringMVC设计理念与DispatcherServlet

    SpringMVC作为Struts2之后异军突起的一个表现层框架,正越来越流行,相信javaee的开发者们就算没使用过SpringMVC,也应该对其略有耳闻.我试图通过对SpringMVC的设计思想和 ...

  9. web前端 —— 移动端知识的一些总结

    个人在移动端的一些总结归纳,有新的知识点会一直更新 一.css部分 1.meta标签 <meta name="viewport" content="width=de ...

  10. Markdown_01_基础语法

    目录 概览 一.区块元素{#BlockElement} 1.段落和换行 2.标题 2.区块引用 2.1 在每行的最前面加上 > 2.2 只在整个段落的第一行最前面加上> 2.3 区块引用可 ...