您的位置:首页 > 其它

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了,调不出来了,心累死了,无奈抄代码呀。

#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: