BZOJ(本校) 3046 简单数学问题 - 线段树
2016-03-07 22:12
295 查看
时限:1s 内存:64MB
题目描述
首先给你一个包含个整数的数列,你需要处理以下两种操作:
1.对区间内的每个数,乘上或者除以一个整数
2.输出区间内每个数的乘积对某个特定模数取模的值
输入格式
输入文件的第一行有两个整数和
第二行包含个整数,表示起始的的值
第三行包含一个整数,表示操作的次数。接下来的行,每行表示一次操作。
对于操作”M L R x”,表示对于区间内的每个数,将它的值乘上
对于操作”D L R x”,表示对于区间内的每个数,将它的值除以
数据保证区间内的每个数都能被整除。
对于操作”“Q L R”,表示询问区间内所有数的乘积对取模的值。
数据保证每次操作中的小于等于。
输出格式
对于每次询问”Q L R”,输出一行表示要求的结果。
样例输入
5 6
10 2 6 9 10
5
Q 1 2
M 1 4 3
Q 1 5
D 1 3 2
Q 1 3
样例输出
2
0
3
但是del的时候会出现del的数和Mod不互质,无法求逆元的情况。
solution:看代码吧,深感表述之累。
代码写wa了,调不出来了,心累死了,无奈抄代码呀。
题目描述
首先给你一个包含个整数的数列,你需要处理以下两种操作:
1.对区间内的每个数,乘上或者除以一个整数
2.输出区间内每个数的乘积对某个特定模数取模的值
输入格式
输入文件的第一行有两个整数和
第二行包含个整数,表示起始的的值
第三行包含一个整数,表示操作的次数。接下来的行,每行表示一次操作。
对于操作”M L R x”,表示对于区间内的每个数,将它的值乘上
对于操作”D L R x”,表示对于区间内的每个数,将它的值除以
数据保证区间内的每个数都能被整除。
对于操作”“Q L R”,表示询问区间内所有数的乘积对取模的值。
数据保证每次操作中的小于等于。
输出格式
对于每次询问”Q L R”,输出一行表示要求的结果。
样例输入
5 6
10 2 6 9 10
5
Q 1 2
M 1 4 3
Q 1 5
D 1 3 2
Q 1 3
样例输出
2
0
3
分析:
用线段树搞很显然。但是del的时候会出现del的数和Mod不互质,无法求逆元的情况。
solution:看代码吧,深感表述之累。
代码写wa了,调不出来了,心累死了,无奈抄代码呀。
#include<cstdio> #include<cmath> #define MAXN 10000 #define MAXKD 10 struct node{ int tag,sum; }tre[MAXKD+10][MAXN*4+10]; int n,Mod,fac[MAXN+10],cntf; void Build(node *tre,int u,int l,int r) { tre[u].sum=1%Mod; tre[u].tag=1%Mod; if(l==r) return ; int mid=(l+r)>>1; Build(tre,u<<1,l,mid),Build(tre,(u<<1)|1,mid+1,r); } void Getfac(int M) { int side=sqrt(M+0.5); for(int i=2;i<=side;i++) if(M%i==0){ fac[++cntf]=i; while(M%i==0) M/=i; } if(M>1) fac[++cntf]=M; } int mypow(int x,long long k) { int ret=1; while(k){ if(k&1) ret=1LL*ret*x%Mod; x=1LL*x*x%Mod; k>>=1; } return ret; } void Push_down(node *tre,int u,int l,int r) { if(!tre[u].tag) return ; tre[u<<1].tag+=tre[u].tag; tre[(u<<1)|1].tag+=tre[u].tag; int mid=(l+r)>>1; tre[u<<1].sum+=tre[u].tag*(mid-l+1); tre[(u<<1)|1].sum+=tre[u].tag*(r-mid); tre[u].tag=0; } void Insert(node *tre,int u,int l,int r,int L,int R,int d) { if(r<L||l>R) return ; if(L<=l&&r<=R){ tre[u].tag+=d; tre[u].sum+=(r-l+1)*d; return ; } Push_down(tre,u,l,r); int mid=(l+r)>>1; Insert(tre,u<<1,l,mid,L,R,d); Insert(tre,(u<<1)|1,mid+1,r,L,R,d); tre[u].sum=tre[u<<1].sum+tre[(u<<1)|1].sum; } void Push_down_re(node *tre,int u,int l,int r) { if(tre[u].tag==1) return ; tre[u<<1].tag=1LL*tre[u<<1].tag*tre[u].tag%Mod; tre[(u<<1)|1].tag=1LL*tre[(u<<1)|1].tag*tre[u].tag%Mod; int mid=(l+r)>>1; tre[u<<1].sum=1LL*tre[u<<1].sum*mypow(tre[u].tag,mid-l+1)%Mod; tre[(u<<1)|1].sum=1LL*tre[(u<<1)|1].sum*mypow(tre[u].tag,r-mid)%Mod; tre[u].tag=1; } void Insert_re(node *tre,int u,int l,int r,int L,int R,int d) { if(l>R||r<L) return ; if(L<=l&&r<=R){ tre[u].tag=1LL*tre[u].tag*d%Mod; tre[u].sum=1LL*tre[u].sum*mypow(d,r-l+1)%Mod; return ; } Push_down_re(tre,u,l,r); int mid=(l+r)>>1; Insert_re(tre,u<<1,l,mid,L,R,d); Insert_re(tre,(u<<1)|1,mid+1,r,L,R,d); tre[u].sum=1LL*tre[u<<1].sum*tre[(u<<1)|1].sum%Mod; } void read() { int x; scanf("%d%d",&n,&Mod); Build(tre[0],1,1,n); Getfac(Mod); for(int i=1;i<=n;i++){ scanf("%d",&x); if(!x){ Insert_re(tre[0],1,1,n,i,i,x); continue; } for(int j=1,cnt;j<=cntf;j++) if(x%fac[j]==0){ cnt=0; while(x%fac[j]==0) x/=fac[j],cnt++; Insert(tre[j],1,1,n,i,i,cnt); } Insert_re(tre[0],1,1,n,i,i,x); } } void Mul(int L,int R,int x) { if(!x){ Insert_re(tre[0],1,1,n,L,R,x); return ; } for(int j=1,cnt;j<=cntf;j++) if(x%fac[j]==0){ cnt=0; while(x%fac[j]==0) x/=fac[j],cnt++; Insert(tre[j],1,1,n,L,R,cnt); } Insert_re(tre[0],1,1,n,L,R,x); } void exgcd(int a,int b,int &d,int &x,int &y) { if(!b){ d=a; x=1,y=0; return ; } exgcd(b,a%b,d,y,x); y-=(a/b)*x; } void Del(int L,int R,int x) { for(int j=1,cnt;j<=cntf;j++) if(x%fac[j]==0){ cnt=0; while(x%fac[j]==0) x/=fac[j],cnt++; Insert(tre[j],1,1,n,L,R,-cnt); } int d,a,b; exgcd(x,Mod,d,a,b); a=(1LL*a%Mod+Mod)%Mod; Insert_re(tre[0],1,1,n,L,R,a); } int Getsum_re(node *tre,int u,int l,int r,int L,int R) { if(r<L||R<l) return 1; if(L<=l&&r<=R) return tre[u].sum; Push_down_re(tre,u,l,r); int mid=(l+r)>>1; return 1LL*Getsum_re(tre,u<<1,l,mid,L,R)*Getsum_re(tre,(u<<1)|1,mid+1,r,L,R)%Mod; } long long Getsum(node *tre,int u,int l,int r,int L,int R) { if(r<L||R<l) return 0; if(L<=l&&r<=R) return tre[u].sum; Push_down(tre,u,l,r); int mid=(l+r)>>1; return 1LL*Getsum(tre,u<<1,l,mid,L,R)+Getsum(tre,(u<<1)|1,mid+1,r,L,R); } int Quary(int L,int R) { int ret=Getsum_re(tre[0],1,1,n,L,R); if(!ret) return 0; for(int i=1;i<=cntf;i++) ret=1LL*ret*mypow(fac[i],Getsum(tre[i],1,1,n,L,R))%Mod; return ret; } void workout() { int Q,L,R,x; char s[20]; scanf("%d",&Q); while(Q--){ scanf("%s",s); if(s[0]=='M'){ scanf("%d%d%d",&L,&R,&x); Mul(L,R,x); } else if(s[0]=='D'){ scanf("%d%d%d",&L,&R,&x); Del(L,R,x); } else{ scanf("%d%d",&L,&R); printf("%d\n",Quary(L,R)); } } } int main() { read(); workout(); return 0; } //powered by Liu junhao's
相关文章推荐
- delphi的日志组件log4d的内存泄露问题
- iOS个人整理22-可视化编辑-XIB
- 浅析LinearLayout的weight属性
- POJ 2528 Mayor's posters(离散化+区间set线段树)
- 最长公共子序列(连续)
- #Android学习#NavigationView基础
- Android开发涉及到的英文
- C语言的编译和链接
- 面试
- 针对三大框架一些面试题
- 蓝桥杯_基础练习《字符串对比---29》
- JVM OOM处理
- 感想
- Linux的用户与权限管理
- 算法导论学习笔记(一)排序算法之快速排序
- C语言常用算法汇总
- Overfitting-Regulization L1\L2正则化
- 解析html语句的JS事件
- 8.11 编程练习
- html DOM和xml DOM的区别于联系