萌新刚学OI,求助线段树
查看原帖
萌新刚学OI,求助线段树
237530
rzh123楼主2022/8/29 09:31
#include <bits/stdc++.h>
#define gc IO::fastgc()
#define pc(c) IO::fastpc(c)
#define int long long
using namespace std;
namespace IO{
	char ibuf[1<<23],obuf[1<<23],*ip1=ibuf,*ip2=ibuf,*o=obuf;
	inline char fastgc(){
		return ((ip1==ip2)&&(ip2=(ip1=ibuf)+fread(ibuf,1,1<<21,stdin),ip1==ip2)?EOF:*ip1++);
	}
	inline void fastpc(char c){
		*(o++)=c;
	}
	inline int read(){
		register int t=0,f=1;
		register char c=gc;
		while(c!='-'&&(c<'0'||c>'9')) c=gc;
		if(c=='-') c=gc,f=-1;
		while(c>='0'&&c<='9') t=10*t+(c^48),c=gc;
		return f*t;
	}
	inline char readc(){
		register char c=gc;
		while(c==' '||c=='\t'||c=='\r'||c=='\n'||c==0||c==EOF) c=gc;
		return c;
	}
	inline void write(int x){
		if(!x) return (void)pc('0');
		if(x<0) pc('-'),x=-x;
		static char c[33]={""};
		static int cc=0;
		while(x) c[++cc]=x%10,x/=10;
		while(cc) pc(c[cc--]|48);
	}
	inline void flush(){
		fwrite(obuf,o-obuf,1,stdout);
	}
	struct IO_Flusher{
		inline IO_Flusher(){}
		inline ~IO_Flusher(){
			flush();
		}
	}__io_flusher_;
}
using IO::read;
using IO::readc;
using IO::write;
constexpr int N=400007,NN=1600007,A=307,PC=77;
constexpr int P=1000000007;
typedef bitset<PC> fset;
int n,q,a[N];
struct Node{
	int l,r,v,lzv;
	fset f,lz;
}tr[NN];
int d[A],pcnt,inv[A];
vector<int> prime;
fset fac[A];
inline void sieve(int n){
	d[1]=1;
	for(int i=2;i<=n;++i){
		if(!d[i]){
			d[i]=i;
			prime.push_back(i);
		}
		for(auto j:prime){
			int t=i*j;
			if(t>n||j>d[i]) break;
			d[t]=j;
		}
	}
}
inline void getinv(int n){
	inv[1]=1;
	for(int i=2;i<=n;++i){
		inv[i]=((-(P/i)*inv[P%i])%P+P)%P;
	}
}
inline int dquery(int _){
	return lower_bound(prime.begin(),prime.end(),_)-prime.begin();
}
inline void buildf(fset &f,int x){
//	printf("bf %d:",x);
	for(int i=2;i*i<=x;++i){
		if(!(x%i)){
//			printf("%d ",i);
			f[dquery(i)]=1;
			while(!(x%i)){
				x/=i;
			}
		}
	}
	if(x>1){
//		printf("%d",x);
		f[dquery(x)]=1;
	}
//	printf("\n");
}
inline void init(int n){
	sieve(n);
	getinv(n);
	pcnt=prime.size();
	for(int i=1;i<=n;++i){
		buildf(fac[i],i);
//		outfset(fac[i]),pc('\n');
	}
//	for(int i=1;i<=n;++i){
//		printf("inv[%lld]=%lld\n",i,inv[i]);
//	}
}
inline void mul(int k,int x,const fset &fx){
	tr[k].v=(tr[k].v*x)%P;
	tr[k].lzv=(tr[k].lzv*x)%P;
	tr[k].f|=fx;
	tr[k].lz|=fx;
}
inline void pushup(int k){
	tr[k].v=tr[k<<1].v*tr[k<<1|1].v%P;
	tr[k].f=tr[k<<1].f|tr[k<<1|1].f;
}
inline void pushdown(int k){
	if(tr[k].lzv!=1){
		mul(k<<1,tr[k].lzv,tr[k].lz);
		mul(k<<1|1,tr[k].lzv,tr[k].lz);
		tr[k].lzv=1;
		tr[k].lz.reset();
	}
}
void build(int k,int l,int r){
	tr[k].l=l,tr[k].r=r,tr[k].lz.reset(),tr[k].lzv=1;
	if(l==r){
		tr[k].v=a[l];
		tr[k].f=fac[a[l]];
		return;
	}
	int m=(l+r)>>1;
	build(k<<1,l,m);
	build(k<<1|1,m+1,r);
	pushup(k);
}
void modify(int k,int l,int r,int x){
	if(tr[k].l>r||tr[k].r<l) return;
	if(tr[k].l>=l&&tr[k].r<=r) return mul(k,x,fac[x]);
	pushdown(k);
	modify(k<<1,l,r,x);
	modify(k<<1|1,l,r,x);
	pushup(k);
}
fset query(int k,int l,int r){
	if(tr[k].l>r||tr[k].r<l) return fac[0];
	if(tr[k].l>=l&&tr[k].r<=r) return tr[k].f;
	fset a;a.reset();
	pushdown(k);
	a|=query(k<<1,l,r);
	a|=query(k<<1|1,l,r);
	return a;
}
int queryv(int k,int l,int r){
	if(tr[k].l>r||tr[k].r<l) return 1;
	if(tr[k].l>=l&&tr[k].r<=r) return tr[k].v;
	int a=1;
	pushdown(k);
	a=a*queryv(k<<1,l,r)%P;
	a=a*queryv(k<<1|1,l,r)%P;
	return a;
}
inline void outfset(const fset &x){
	for(int i=0;i<pcnt;++i){
		if(x[i]){
			printf("%lld(%lld) ",i,prime[i]);
		}
	} 
}
signed main(){
	int l,r,x;
	fset t;
	init(300);
	n=read(),q=read();
	for(register int i=1;i<=n;++i){
		a[i]=read();
	}
	build(1,1,n);
	while(q--){
		switch(readc()){
			case 'M':{
				l=read(),r=read(),x=read();
				modify(1,l,r,x);
				break;
			}
			case 'T':{
				l=read(),r=read();
				t=query(1,l,r);
				x=queryv(1,l,r);
//				printf("t=");outfset(t);printf("\n");
//				printf("x=%lld\n",x);
				for(register int i=0;i<pcnt;++i){
					if(t[i]){
						x=x*(prime[i]-1)%P;
						x=x*inv[prime[i]]%P;
					}
				}
				write(x),pc('\n');
				break;
			}
		}
	}
	return 0;
}

思路就是用线段树维护区间乘积、区间中出现的质因数,然后暴力算欧拉函数。

但是,WA on #3。

有没有大佬能看看有什么问题,或者给个规模较小的 hack?

2022/8/29 09:31
加载中...