首页 > 其他分享 >CF1114F Please, another Queries on Array?

CF1114F Please, another Queries on Array?

时间:2024-07-12 20:31:48浏览次数:18  
标签:rt return rs int tr CF1114F Please ans Array

一道很好的线段树+求欧拉函数题!!!
先简单理解一下题意:给你一段长度为n的区间,q次操作,输入为1时将l~r区间每个数乘上x,输入为2时求解\(\varphi(\prod_{i=l} ^{r} {a_i})\) 。

赛时心历经过:
第一眼感觉是个线段树板子题,赛时也是这么想的,打到一半发现不对劲,首先这个乘积就没法维护,随便乘两下就炸了,再其次这么大的数我也不会求\(\varphi\)值呀但打都打了就只能硬着头皮打下去,厉害的是我一个线段树一遍就打过了(当然仅限于小样例),抱着侥幸心理交了,不出所料的爆零了。

赛后去查了一下怎么能利用\(\varphi\)的性质优化一下然后就发现了这么一个已经被我遗忘的东西

\[\varphi(n)=n\times \prod_{i=1}^{k}{(1- \frac{1}{p_i})} \]

其中\(p_1,p_2...p_n\)为n的所有质因数,n为正整数
这样搞的话就可以边\(mod\)边乘了!
用线段树维护两个东西一个是\(a[i]\)的乘积,一个是后面那一坨连乘,\(a[i]\)的乘积很好维护,但就是后面那一坨,(⊙o⊙)…难以描述,只好集思广益一下,得出结果:
把\(1-300\)里的质数预处理出来,发现只有62个,嘿嘿嘿(一脸坏笑),long long 好像可以存63位是吧,那就不好意思了,直接就是状压一下最后统计这个区间里的所有质因数。
问题迎刃而解!!!
最后附上代码::

#include<bits/stdc++.h>
#define int long long
#define ls rt<<1
#define rs rt<<1|1
using namespace std;
const int N=4e5+5,p=1e9+7;
int n,m,t;
int z,x,y,tot,a[N]; 
int phi[N],prime[N];
string op;
struct sb{
	int l,r,x,lazy1,lazy2=1,size,phi;
}tr[N<<2];
int qp(int a,int n){
    int ans=1;
    while(n){
        if(n&1)ans=ans*a%p;
        a=a*a%p;
        n>>=1;
    }
    return ans;
}
int ny(int x){
	return qp(x,p-2);
}
void iint(){
    for(int i=2;i<=300;i++){
    	bool vis=0;
    	for(int j=2;j<=sqrt(i);j++){
    		if(i%j==0)vis=1;
		}if(vis==0)prime[++tot]=i,phi[tot]=(i-1)*ny(i)%p;
	}
}
void pushup(int rt){
	tr[rt].x=tr[ls].x*tr[rs].x%p;
	tr[rt].size=tr[ls].size+tr[rs].size;
	tr[rt].phi=(tr[ls].phi|tr[rs].phi);
}
void pushdown(int rt){
	int l1=tr[rt].lazy1;
	if(l1){
		tr[ls].phi=(tr[ls].phi|l1);
		tr[rs].phi=(tr[rs].phi|l1);
		tr[ls].lazy1|=l1;
		tr[rs].lazy1|=l1;
		tr[rt].lazy1=0;
	}
	int l2=tr[rt].lazy2;
	if(l2!=1){
		tr[ls].x=tr[ls].x*qp(l2,tr[ls].size)%p;
		tr[rs].x=tr[rs].x*qp(l2,tr[rs].size)%p;
		tr[ls].lazy2=tr[ls].lazy2*l2%p;
		tr[rs].lazy2=tr[rs].lazy2*l2%p;
		tr[rt].lazy2=1;
	}
}
void build(int rt,int l,int r){
	tr[rt].l=l;
	tr[rt].r=r;
	if(l==r){
		tr[rt].x=a[l];
		tr[rt].size=1;
		for(int i=1;i<=tot;i++){
			if(a[l]%prime[i]==0){
				tr[rt].phi=(tr[rt].phi|(1ll<<i));
			}
		}
		return;
	}
	int mid=(l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	pushup(rt);
}
void change(int rt,int l,int r,int x){
	if(tr[rt].l>=l&&tr[rt].r<=r){
		int sum=0;
		for(int i=1;i<=tot;i++){
			if(x%prime[i]==0){
				sum=(sum|(1ll<<i));
			}
		}
		tr[rt].x=tr[rt].x*qp(x,tr[rt].size)%p;
		tr[rt].phi|=sum;
		tr[rt].lazy1|=sum;
		tr[rt].lazy2=tr[rt].lazy2*x%p;
		return;
	}
	pushdown(rt);
	int mid=(tr[rt].l+tr[rt].r)>>1;
	if(l<=mid)change(ls,l,r,x);
	if(r>mid)change(rs,l,r,x);
	pushup(rt);
}
int query(int rt,int l,int r){
	pushdown(rt);
	if(tr[rt].l>=l&&tr[rt].r<=r)return tr[rt].x;
	int mid=(tr[rt].l+tr[rt].r)>>1;
	int ans=1;
	if(l<=mid)ans=ans*query(ls,l,r)%p;
	if(r>mid)ans=ans*query(rs,l,r)%p;
	return ans%p;
}
int Query(int rt,int l,int r){
	pushdown(rt);
	if(tr[rt].l>=l&&tr[rt].r<=r){
		return tr[rt].phi;
	}
	int mid=(tr[rt].l+tr[rt].r)>>1;
	int ans=0;
	if(l<=mid)ans=(ans|Query(ls,l,r));
	if(r>mid)ans=(ans|Query(rs,l,r));
	return ans;
}
signed main(){
//	freopen("array.in","r",stdin);
//	freopen("array.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	iint();
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	build(1,1,n);
	while(m--){
		cin>>op>>x>>y;
		if(op[0]=='1'){
			cin>>z;
			change(1,x,y,z);
		}
		else{
			int k=Query(1,x,y);
			int sum=1;
			for(int i=1;i<=62;i++){
				if((k>>i)&1)sum=sum*phi[i]%p;
			}
			int aaa=query(1,x,y);
			cout<<aaa*sum%p<<endl;
		}
	}
	return 0;
}

完结撒花!!!

标签:rt,return,rs,int,tr,CF1114F,Please,ans,Array
From: https://www.cnblogs.com/houburzyx/p/18299327

相关文章

  • 2-ArrayList底层结构和源码分析
    2-ArrayList底层结构和源码分析介绍汇总:ArrayList的注意事项ArrayList的运行重要步骤补充1-ArrayList的注意事项ArrayList允许添加所有的元素,包括null,而且还可以多个null。ArrayList是由数组来实现数据存储的。ArrayList基本等同于Vector,除了ArrayList是线......
  • 0081_Search-in-Rotated-Sorted-Array-II【M】pivot 有序数组(值可重复)中的查找数值
    JY:pivot有序数组(值可重复)中的查找数值1、二分查找该题的任何解法同样可用于0033_search-in-rotated-sorted-array【M】中nums可能包含重复元素,这会影响到程序的时间复杂度吗?会,使用二分查找局部有序时,当nums[mid]==nums[low]时(或其它类似情况),无法确定左侧区间还是右......
  • div3E. Beautiful Array
    目录E.BeautifulArray原题链接题目思路代码E.BeautifulArray原题链接题目思路代码//https://codeforces.com/contest/1986/problem/E#include<bits/stdc++.h>#definecaseT\intT;\cin>>T;\while(T--)usingnamespacestd;usingll=lo......
  • day1-array-part01-7.3
    taskfortoday:1.数组理论基础,2.704.二分查找,3.27.移除元素-------------------------------1.数组理论基础-数组是存放在连续内存空间上的相同类型数据的集合。-数组内存不能删除只能覆盖-注意与容器的区别2.704二分查找二分法的两个条件:(1)有序数组;(2)无......
  • day2-array-part02-7.4
    taskfortoday1.977.有序数组的平方 2,209.长度最小的子数组 3.59.螺旋矩阵II---------------------------------------------1.977.有序数组的平方 -暴力法raiseeachelementinthearraytothepowerof2,andthensorttheminascendingorder.it......
  • OC-NSArray的基本介绍
    NSArray是不可变的;存储不同类型的对象。这意味着一个NSArray可以同时包含NSString、NSNumber、NSDictionary等不同类型的对象。同时只能存储对象,不能直接存储基本数据类型(如int、float等)。如果需要存储基本数据类型,应该先将它们封装为相应的对象类型(如NSNumber或NSValue)。......
  • codeforces1849 D. Array Painting
    题目链接https://codeforces.com/problemset/problem/1849/D题意输入\(n(1\leqn\leq2e5)\)和长为\(n\)的数组\(a(0\leqa[i]\leq2)\)。最初,数组的每个元素都是蓝色的。有两种类型的操作:支付一枚硬币,选择一个蓝色元素,将其涂成红色。选择一个不等于\(0\)的红......
  • [LeetCode] 238. Product of Array Except Self
    坑真的很多,首先要处理全零reduce没有值typeerror的问题。classSolution:defproductExceptSelf(self,nums:List[int])->List[int]:total=reduce(mul,nums)ret=[]iftotal==0:try:total=reduce(mul,[......
  • return isPlainObject(res) || Array.isArray(res) ? observer(res, cb) : res; 这个
    这段代码主要是在实现一个深度观察者模式的部分逻辑,用于递归地处理对象和数组,以便在数据结构变化时触发回调。这里的关键是理解条件运算符和函数调用的执行顺序。让我们逐步分析:条件表达式的左侧:isPlainObject(res):这个函数检查res是否是一个纯对象(即普通的JavaScript对象......
  • HashTable,ArrayList,queue等常用方法
    HashTable,ArrayList,queue等常用方法HashMap是Java中非常常用的集合类,它存储键值对,并提供了一系列方便的方法来操作这些数据。以下是一些HashMap的常用方法:1.添加和获取元素:put(key,value):将指定的键值对添加到HashMap中。如果键已存在,则更新对应的值。get(ke......