[codeforces]Round #538 (Div. 2) F. Please, another Queries on Array?
题解:
$$ ans=F\left ( \prod _{i=l}^{r}a_i \right ) $$
$$ =(p_i-1){p_i}^{k_i-1}*.....*(p_j-1){p_j}^{k_j-1} $$
$$={p_i}^{k_i}*.....*{p_j}^{k_j}*(\frac{p_i-1}{p_i}*......*\frac{p_j-1}{p_j}) $$
因为数据范围保证$ a_i\leq 300 $ 所以在这个范围内只有62个素因子 我们可以直接每一位对应一bit 来判断区间中某个素因子是否出现 然后查询就行了
(常数写的有点大....懒得优化了
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=4e5+10; const double eps=1e-8; #define ll long long const int mod=1e9+7; using namespace std; struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } ll ksm(ll a,ll b){ ll ans=1; while(b){ if(b&1)ans=ans*a%mod; a=a*a%mod;b=b>>1; } return ans; } ll key[MAXN<<2],tag[MAXN<<2],sum[MAXN<<2],flag[MAXN<<2]; int a[MAXN]; int vis[305],p[MAXN]; void push(int rt,int l,int r){ if(tag[rt]!=1){ int mid=(l+r)>>1; tag[rt<<1]*=tag[rt];tag[rt<<1]%=mod; tag[rt<<1|1]*=tag[rt];tag[rt<<1|1]%=mod; sum[rt<<1]*=ksm(tag[rt],mid-l+1);sum[rt<<1]%=mod; sum[rt<<1|1]*=ksm(tag[rt],r-mid);sum[rt<<1|1]%=mod; tag[rt]=1; } if(flag[rt]){ key[rt<<1]|=flag[rt];key[rt<<1|1]|=flag[rt]; flag[rt<<1]|=flag[rt];flag[rt<<1|1]|=flag[rt]; flag[rt]=0; } } void up(int x){ key[x]=(key[x<<1]|key[x<<1|1]); sum[x]=(sum[x<<1]*sum[x<<1|1])%mod; } void built(int rt,int l,int r){ tag[rt]=1; if(l==r){ sum[rt]=1; for(int i=2;i*i<=a[l];i++){ if(a[l]%i==0){ int num=0; while(a[l]%i==0)num++,a[l]/=i; sum[rt]=sum[rt]*ksm(i,num)%mod; key[rt]|=(1LL<<vis[i]); } } if(a[l]!=1){ sum[rt]=(sum[rt]*a[l])%mod; key[rt]|=(1LL<<vis[a[l]]); } return ; } int mid=(l+r)>>1; built(rt<<1,l,mid); built(rt<<1|1,mid+1,r); up(rt); } ll v1,v2; void update(int rt,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ tag[rt]*=v1;tag[rt]%=mod;flag[rt]|=v2; sum[rt]*=ksm(v1,r-l+1);key[rt]|=v2; return ; } int mid=(l+r)>>1; push(rt,l,r); if(ql<=mid)update(rt<<1,l,mid,ql,qr); if(qr>mid)update(rt<<1|1,mid+1,r,ql,qr); up(rt); } ll ans1,ans2; void query(int rt,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ ans1*=sum[rt];ans1%=mod;ans2|=key[rt]; return ; } int mid=(l+r)>>1; push(rt,l,r); if(ql<=mid)query(rt<<1,l,mid,ql,qr); if(qr>mid)query(rt<<1|1,mid+1,r,ql,qr); up(rt); } int main(){ int cnt=0; inc(i,2,300){ bool flag=0; for(int j=2;j*j<=i;j++){ if(i%j==0){flag=1;break;} } if(!flag)vis[i]=cnt++,p[cnt-1]=i; } int n=read();int m=read(); inc(i,1,n)a[i]=read(); built(1,1,n); char str[11];int l,r,x; while(m--){ scanf("%s",str); l=read();r=read(); if(str[0]=='T'){ ans1=1;ans2=0;query(1,1,n,l,r); for(int i=61;i>=0;i--){ if((ans2>>i)&1)ans1*=((p[i]-1)*ksm(p[i],mod-2)%mod),ans1%=mod; } printf("%lld\n",ans1); } else{ x=read(); v1=1;v2=0; for(int i=2;i*i<=x;i++){ if(x%i==0){ int num=0; while(x%i==0)num++,x/=i; v1=v1*ksm(i,num)%mod; v2|=(1LL<<vis[i]); } } if(x!=1){ v1=(v1*x)%mod; v2|=(1LL<<vis[x]); } update(1,1,n,l,r); } } return 0; }