您的位置:首页 > 其它

【分解质因数】【树状数组】【快速幂】codeforces 2014 ACM-ICPC Vietnam National Second Round E. ACM

2015-03-14 19:25 399 查看
乘除都在150以内,分解质因数后发现只有35个,建立35个树状数组/线段树,做区间加、区间查询,最后快速幂起来。

#include<cstdio>
#include<cstring>
using namespace std;
#define N 50001
typedef long long ll;
ll Quick_Pow(ll a,ll p,ll MOD)
{
if(!p) return 1;
ll ans=Quick_Pow(a,p>>1,MOD);
ans=ans*ans%MOD;
if((p&1)==1) ans=ans*a%MOD;
return ans;
}
int zu,n,m;
int prime[151],en,zyz[151][40];
bool vis[151];
struct BIT
{
ll d
;
void add_node(int p,const ll &v)
{for(;p<=n;p+=(p&(-p)))d[p]+=v;}
ll query(int p)
{ll res=0;for(;p;p-=(p&(-p)))res+=d[p];return res;}
void clear(){memset(d,0,sizeof(d));}
}T[40];
struct BIT2
{
ll d
;
void add_node(int p,const ll &v)
{for(;p<=n;p+=(p&(-p)))d[p]+=v;}
void add_range(const int &L,const int &R,const ll &v)
{add_node(L,v);if(R!=n)add_node(R+1,-v);}
ll query(int p)
{ll res=0;for(;p;p-=(p&(-p)))res+=d[p];return res;}
void clear(){memset(d,0,sizeof(d));}
}T2[40];
void Shai()
{
vis[1]=1;
for(int i=2;i<=150;i++)
{
if(!vis[i]) prime[++en]=i;
for(int j=i*i;j<=150;j+=i)
vis[j]=1;
}
}
void add(const int &wh,const int &p,const int &v)
{
T[wh].add_node(p,(ll)v*(ll)p);
if(p!=1) T2[wh].add_range(1,p-1,(ll)v);
}
void Add(const int &wh,const int &L,const int &R,const int &v)
{
add(wh,R,v);
if(L!=1) add(wh,L-1,(ll)(-v));
}
ll query(const int &wh,const int &p)
{
return T[wh].query(p)+T2[wh].query(p)*(ll)p;
}
ll Query(const int &wh,const int &L,const int &R)
{
return query(wh,R)-(L==1?0:query(wh,L-1));
}
ll QUERY(const int &wh,const int &L,const int &R)
{
if(L<=R) return Query(wh,L,R);
else return Query(wh,L,n)+Query(wh,1,R);
}
int main()
{
int op,x,y,v;
Shai();
for(int i=1;i<=150;++i)
{
int t=i;
for(int j=1;j<=en;++j)
while(t%prime[j]==0)
{
t/=prime[j];
++zyz[i][j];
}
}
scanf("%d",&zu);
for(;zu;--zu)
{
for(int i=1;i<=en;++i)
{
T[i].clear();
T2[i].clear();
}
scanf("%d%d",&n,&m);
for(;m;--m)
{
scanf("%d%d%d%d",&op,&x,&y,&v);
if(op==1)
{
for(int i=1;i<=en;++i)
if(zyz[v][i])
{
if(x<=y)
Add(i,x,y,zyz[v][i]);
else
{
Add(i,x,n,zyz[v][i]);
Add(i,1,y,zyz[v][i]);
}
}
}
else if(op==2)
{
for(int i=1;i<=en;++i)
if(zyz[v][i])
{
if(x<=y)
Add(i,x,y,-zyz[v][i]);
else
{
Add(i,x,n,-zyz[v][i]);
Add(i,1,y,-zyz[v][i]);
}
}
}
else
{
ll ans=1;
for(int i=1;i<=en;++i)
ans=(ans*Quick_Pow((ll)prime[i],QUERY(i,x,y),(ll)v))%(ll)v;
printf("%I64d\n",ans);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: