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. window 中安装 redis的遇到的一此bug

    一.下载 链接:https://github.com/MicrosoftArchive/redis/releases   说明: 如果是是下载msi版本的话会默认帮我们配置好测试 环境,如果是下载zi ...

  2. git tags 管理

    新建标签: git tag -a V1.1 -m "some thing" (新建标签前请先commit代码) 推送标签: git push --tags (推送标签前请先推送代码 ...

  3. 关于 Token,你应该知道的十件事

    转自:http://ju.outofmemory.cn/entry/134189 原文是一篇很好的讲述 Token 在 Web 应用中使用的文章,而这是我和 Special 合作翻译的译文. 1. T ...

  4. url 、src 、href 的区别

    url.href.src 详解 现自己居然没把url.href.src关系及使用搞清楚,今天就理一下.主要包括:url.src.href定义以及使用区别. URL(Uniform Resource L ...

  5. TestNG入门--安装和基本介绍

    TestNG介绍 TestNG是Java中的一个测试框架, 类似于JUnit 和NUnit,   功能都差不多, 只是功能更加强大,使用也更方便 Java中已经有一个JUnit的测试框架了.  Tes ...

  6. 为什么U盘在拔出之前需要“安全弹出”?

    前言 我们不知道从什么时候开始有一个观念:U盘一定要点击“安全弹出”才能拔.那么是不是在任何情况下都必须要这样呢? 介绍 U盘的传输策略有两种: 写入缓存:这种策略在windows中称为“更好的性能” ...

  7. ManualResetEvent(ManualResetEvent : EventWaitHandle : WaitHandle)的三个方法

    ManualResetEvent mre= new ManualResetEvent(false);(ManualResetEvent : EventWaitHandle : WaitHandle) ...

  8. CCS5 学习笔记1

    CCS5 学习笔记1 2013-09-15 10:35:49 周日边学习ccs5使用边写笔记,准备用一天时间好好学习下ccs5怎么使用,便于以后工作向ccs5平台迁移!

  9. SPOJ-394-ACODE - Alphacode / dp

    ACODE - Alphacode #dynamic-programming Alice and Bob need to send secret messages to each other and ...

  10. UVA-1611 Crane (构造)

    题目大意:给一个1~n的序列,每次操作可以把长度为偶数的序列交换前一半和后一半的位置.求出将这个序列变成升序的步骤. 题目分析:构造求解. 代码如下: # include<iostream> ...