CF1114F Please, another Queries on Array?

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
",prod);
				}
		}
	return 0;
}
原文地址:https://www.cnblogs.com/jklover/p/10388865.html