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

乘除都在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[N];
	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[N];
	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
",ans);
	  	  	  }
	  	  }
	  }
	return 0;
}
原文地址:https://www.cnblogs.com/autsky-jadek/p/4338083.html