Codeforces 1114F Please, another Queries on Array? [线段树,欧拉函数]
洛谷:咕咕咕
CF少有的大数据结构题。
思路
考虑一些欧拉函数的性质:
\varphi(p^k)=p^{k-1}\times (p-1)=p^k \times \frac{p-1}{p},k>0\\
\varphi(ab)=\varphi(a)\varphi(b),gcd(a,b)=1\\
\dots
\]
有上面三个就够了。
要求
\]
可以考虑把\(\prod a_i\)拆成
\]
则有
ans&=\varphi(\prod a_i)\\
&=\prod \varphi(p_i ^{k_i})\\
&=\prod p_i ^{k_i}\times \frac{p_i-1}{p_i}\\
&=\prod a_i \prod \frac{p_i-1}{p_i}
\end{align*}
\]
发现前面那个只和一段的积有关,后面只和每个质数是否出现有关。
于是可以维护区间积、区间是否出现。筛一下发现\(\le 300\)的质数只有\(62\)个,状压即可。
复杂度\(O(n\log n+q\log^2 n)\),鬼知道这东西怎么跑过去\(n=4\times 10^5,q=2\times 10^5\)的……CF机子厉害呀。
代码
#include<bits/stdc++.h>
namespace my_std{
using namespace std;
#define pll pair<ll,ll>
#define fir first
#define sec second
#define MP make_pair
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define drep(i,x,y) for (int i=(x);i>=(y);i--)
#define go(x) for (int i=head[x];i;i=edge[i].nxt)
#define sz 404040
#define mod (ll(1e9+7))
typedef long long ll;
typedef double db;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template<typename T>inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
template<typename T>inline void read(T& t)
{
t=0;char f=0,ch=getchar();double d=0.1;
while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
t=(f?-t:t);
}
template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
void file()
{
#ifndef ONLINE_JUDGE
freopen("a.txt","r",stdin);
#endif
}
#ifdef mod
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
ll inv(ll x){return ksm(x,mod-2);}
#else
ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
#endif
// inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;
int n,Q;
int pri[66],cnt;
bool npri[333];
void init()
{
int n=300;
#define xx (i*pri[j])
rep(i,2,n)
{
if (!npri[i]) pri[++cnt]=i;
rep(j,1,cnt)
{
if (xx>n) break;
npri[xx]=1;
if (i%pri[j]==0) break;
}
}
#undef xx
}
ll tr[sz<<2],tag[sz<<2];
ll S[sz<<2],tg[sz<<2];
#define ls k<<1
#define rs k<<1|1
#define lson ls,l,mid
#define rson rs,mid+1,r
void Mul(int k,int l,int r,ll mul){tag[k]=tag[k]*mul%mod;tr[k]=tr[k]*ksm(mul,r-l+1)%mod;}
void Or(int k,ll s){S[k]|=s;tg[k]|=s;}
void pushdown(int k,int l,int r)
{
int mid=(l+r)>>1;
if (tag[k]!=1) { Mul(lson,tag[k]); Mul(rson,tag[k]); }
Or(ls,tg[k]);Or(rs,tg[k]);
tag[k]=1;tg[k]=0;
}
void pushup(int k){tr[k]=tr[ls]*tr[rs]%mod;S[k]=S[ls]|S[rs];}
void update(int k,int l,int r,int x,int y,ll mul,ll s)
{
if (x<=l&&r<=y) return Mul(k,l,r,mul),Or(k,s);
int mid=(l+r)>>1;
pushdown(k,l,r);
if (x<=mid) update(lson,x,y,mul,s);
if (y>mid) update(rson,x,y,mul,s);
pushup(k);
}
pll query(int k,int l,int r,int x,int y)
{
if (x<=l&&r<=y) return MP(tr[k],S[k]);
pushdown(k,l,r);
int mid=(l+r)>>1;
pll ret(1,0),L,R;
if (x<=mid) L=query(lson,x,y),ret.fir=ret.fir*L.fir%mod,ret.sec|=L.sec;
if (y>mid) R=query(rson,x,y),ret.fir=ret.fir*R.fir%mod,ret.sec|=R.sec;
return ret;
}
void build(int k,int l,int r)
{
tag[k]=1;tg[k]=0;
if (l==r)
{
int x;read(x);
tr[k]=x;
rep(i,1,cnt)
if (x%pri[i]==0)
S[k]|=(1ll<<(i-1));
return;
}
int mid=(l+r)>>1;
build(lson);build(rson);
pushup(k);
}
ll query(int l,int r)
{
pll x=query(1,1,n,l,r);
ll ret=x.fir;
rep(i,1,cnt)
if (x.sec&(1ll<<(i-1)))
ret=ret*(pri[i]-1)%mod*inv(pri[i])%mod;
return ret;
}
void modify(int l,int r,int x)
{
ll s=0;
rep(i,1,cnt)
if (x%pri[i]==0)
s|=(1ll<<(i-1));
update(1,1,n,l,r,x,s);
}
int main()
{
file();
init();
read(n,Q);
build(1,1,n);
char s[10];
int x,y,z;
while (Q--)
{
scanf("%s",s);read(x,y);
if (s[0]=='T') printf("%I64d\n",query(x,y));
else read(z),modify(x,y,z);
}
return 0;
}
Codeforces 1114F Please, another Queries on Array? [线段树,欧拉函数]的更多相关文章
- Codeforces 1114F Please, another Queries on Array? 线段树
Please, another Queries on Array? 利用欧拉函数的计算方法, 用线段树搞一搞就好啦. #include<bits/stdc++.h> #define LL ...
- 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}\) 由欧拉函数是积性函数得: \[ ...
- BZOJ 3813--奇数国(线段树&欧拉函数&乘法逆元&状态压缩)
3813: 奇数国 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 755 Solved: 432[Submit][Status][Discuss] ...
- 【bzoj3813】: 奇数国 数论-线段树-欧拉函数
[bzoj3813]: 奇数国 题意:给定一个序列,每个元素可以分解为最小的60个素数的形式.(x=p1^k1*p2^k2*......p60^k60)(p1=2,p2=3,…,p60=281) 支持 ...
- [bzoj3813] 奇数国 [线段树+欧拉函数]
题面 传送门 思路 这题目是真的难读......阅读理解题啊...... 但是理解了以后就发现,题目等价于: 给你一个区间,支持单点修改,以及查询一段区间的乘积的欧拉函数值,这个答案对19961993 ...
- 线段树+欧拉函数——cf1114F
调了半天,写线段树老是写炸 /* 两个操作 1.区间乘法 2.区间乘积询问欧拉函数 欧拉函数计算公式 phi(mul(ai))=mul(ai) * (p1-1)/p1 * (p2-1)/p2 * .. ...
- Please, another Queries on Array? CodeForces - 1114F (线段树,欧拉函数)
这题刚开始看成求区间$\phi$和了........先说一下区间和的做法吧...... 就是说将题目的操作2改为求$(\sum\limits_{i=l}^{r}\phi(a[i]))\%P$ 首先要知 ...
- BZOJ4869 六省联考2017相逢是问候(线段树+欧拉函数)
由扩展欧拉定理,a^(a^(a^(……^x)))%p中x作为指数的模数应该是φ(φ(φ(φ(……p)))),而p取log次φ就会变为1,也即每个位置一旦被修改一定次数后就会变为定值.线段树维护区间剩余 ...
- 【BZOJ3813】奇数国 线段树+欧拉函数
[BZOJ3813]奇数国 Description 给定一个序列,每次改变一个位置的数,或是询问一段区间的数的乘积的phi值.每个数都可以表示成前60个质数的若干次方的乘积. Sample Input ...
随机推荐
- GCC编译器原理(一)------GCC 工具:addr2line、ar、as、c++filt和elfedit
1.3 GCC 工具 1.3.1 binutils 工具集 工具 描述 addr2line 给出一个可执行文件的内部地址,addr2line 使用文件中的调试信息将地址翻译成源代码文件名和行号. ar ...
- 符号执行-基于python的二进制分析框架angr
转载:All Right 符号执行概述 在学习这个框架之前首先要知道符号执行.符号执行技术使用符号值代替数字值执行程序,得到的变量的值是由输入变 量的符号值和常量组成的表达式.符号执行技术首先由Kin ...
- datatable转换为list<model> 映射
using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.R ...
- 第26月第29天 ffmpeg yasm
1. brew install automake fdk-aac git lame libass libtool libvorbis libvpx \ opus sdl shtool texi2htm ...
- 堆(heap)与栈(stack)
编程语言书籍中经常解释: 值类型被创建在栈上,引用类型被创建在堆上. 构造函数,原型之类的算是引用类型吗? 5种基本数据类型有Undefined.Null.Boolean.Number 和 Str ...
- LR-Controller 如何自定义显示虚拟用户状态
我们压测时,如何直观,实时地查看当前运行账号和迭代情况呢. 在运行脚本中添加一行代码就解决了~~~~~~~~~~~
- lua 的元表与元方法
1. 元表与元方法, 相当于C++的函数重载 参考链接: https://blog.csdn.net/yueya_shanhua/article/details/52233228
- 🍓 redux示例 🍓
- Linux常用命令(三)查看当前计算机各方面信息
1.查看cpu: top 2.查看当前linux版本:name -a 查看当前运行的内核版本:cat /pro/version 查看发行版本信息:cat /etc/issue 查看上面所有信息:lsb ...
- synchronized与Lock的区别与使用
1.ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候 线程A和B都要获取对象obj的锁定,假设A获取了对象obj锁,B将等待A ...