【NOIP2016提高組A組7.16】第三條跑道
阿新 • • 發佈:2018-05-09
以及 span const queue als TP 分析 namespace 技術分享
題目
數據範圍
分析
時限5000ms。
我們註意到\(a_{i}初始值以及x小於等於600且非零\)
也就是說,\(a_{i}\)的質因數一定小於600,而600以內的質因數只有109個。
那麽考慮常用於區間修改的線段樹。
用線段樹來維護某個位置的某個質因數的總乘積,以及某個質因數出現的位置的個數。
時間復雜度\(O(QlogN·109)\)
#include <cmath> #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> const long long maxlongint=2147483647; const long long mo=100000007; const long long N=50005; using namespace std; struct ddx { long long a[120],v[120],lazy[120],sum[120]; }tree[50005]; long long ss[80000],n,m,ny[1000005],belong[1000005]; long long ans,re[10005]; bool b[1000005]; long long mi(long long x,long long y) { long long sum=1; while(y) { if(y&1) sum=x*sum%mo; x=x*x%mo; y/=2; } return sum; } long long put(long long v,long long l,long long r,long long x,long long y,long long z) { if(l==r) { tree[v].a[y]=z; tree[v].v[y]=tree[v].v[y]*mi(ss[y],z)%mo; tree[v].sum[y]=1; return 0; } long long mid=(l+r)/2; if(x<=mid) put(v*2,l,mid,x,y,z); else put(v*2+1,mid+1,r,x,y,z); for(long long i=1;i<=109;i++) { tree[v].a[i]=(tree[v*2].a[i]+tree[v*2+1].a[i])%mo; tree[v].v[i]=tree[v*2].v[i]*tree[v*2+1].v[i]%mo; tree[v].sum[i]=tree[v*2].sum[i]+tree[v*2+1].sum[i]; } } long long down(long long v,long long mid,long long l,long long r,long long y) { if(!tree[v].lazy[y]) return 0; long long z=tree[v].lazy[y]; tree[v*2].a[y]+=z*(mid-l+1); tree[v*2+1].a[y]+=z*(r-mid); tree[v*2].v[y]=tree[v*2].v[y]*mi(ss[y],z*(mid-l+1))%mo; tree[v*2+1].v[y]=tree[v*2+1].v[y]*mi(ss[y],z*(r-mid))%mo; tree[v*2].lazy[y]+=z; tree[v*2+1].lazy[y]+=z; tree[v*2].sum[y]=(mid-l+1); tree[v*2+1].sum[y]=(r-mid); tree[v].lazy[y]=0; } long long change(long long v,long long l,long long r,long long x,long long x1,long long y,long long z) { if(l==x && r==x1) { tree[v].a[y]=(tree[v].a[y]+z*(r-l+1))%mo; tree[v].v[y]=tree[v].v[y]*mi(ss[y],z*(r-l+1))%mo; tree[v].sum[y]=(r-l+1); tree[v].lazy[y]+=z; return 0; } long long mid=(l+r)/2; for(long long i=1;i<=109;i++) down(v,mid,l,r,i); if(x1<=mid) change(v*2,l,mid,x,x1,y,z); else if(x>mid) change(v*2+1,mid+1,r,x,x1,y,z); else change(v*2,l,mid,x,mid,y,z),change(v*2+1,mid+1,r,mid+1,x1,y,z); for(long long i=1;i<=109;i++) { tree[v].a[i]=(tree[v*2].a[i]+tree[v*2+1].a[i])%mo; tree[v].v[i]=tree[v*2].v[i]*tree[v*2+1].v[i]%mo; tree[v].sum[i]=tree[v*2].sum[i]+tree[v*2+1].sum[i]; } } long long find(long long v,long long l,long long r,long long x,long long x1) { if(l==x && r==x1) { for(long long i=1;i<=109;i++) { if(tree[v].sum[i]) ans=ans*tree[v].v[i]%mo*mi(ny[ss[i]],tree[v].sum[i])%mo*mi(ss[i]-1,tree[v].sum[i])%mo; } return 0; } long long mid=(l+r)/2; for(long long i=1;i<=109;i++) down(v,mid,l,r,i); if(x1<=mid) find(v*2,l,mid,x,x1); else if(x>mid) find(v*2+1,mid+1,r,x,x1); else find(v*2,l,mid,x,mid),find(v*2+1,mid+1,r,mid+1,x1); for(long long i=1;i<=109;i++) { tree[v].a[i]=(tree[v*2].a[i]+tree[v*2+1].a[i])%mo; tree[v].v[i]=tree[v*2].v[i]*tree[v*2+1].v[i]%mo; tree[v].sum[i]=tree[v*2].sum[i]+tree[v*2+1].sum[i]; } } int main() { memset(b,true,sizeof(b)); b[0]=0; b[1]=0; for(long long i=2;i<=10000;i++) { if(b[i]) { ss[++ss[0]]=i; ny[i]=mi(i,mo-2); belong[i]=ss[0]; } for(long long j=1;j<=ss[0];j++) { if(i*ss[j]<=10000) b[i*ss[j]]=false; else break; if(!(i%ss[j])) break; } } scanf("%lld",&n); for(long long i=1;i<=50001;i++) for(long long j=1;j<=110;j++) tree[i].v[j]=1; for(long long j=1;j<=n;j++) { scanf("%lld",&re[j]); long long p=re[j]; if(b[p]) { put(1,1,n,j,belong[p],1); } else { for(long long k=1;ss[k]<=sqrt(re[j]) && p>1;k++) { long long w=0; while(!(p%ss[k])) { p/=ss[k]; w++; } if(w) { put(1,1,n,j,k,w); } } if(p>1) { put(1,1,n,j,belong[p],1); } } } long long q; scanf("%lld",&q); for(long long i=1;i<=q;i++) { long long t,x,y,z; scanf("%lld%lld%lld",&t,&x,&y); if(t) { ans=1; find(1,1,n,x,y); printf("%lld\n",ans); } else { scanf("%lld",&z); long long p=z; if(b[p]) { change(1,1,n,x,y,belong[p],1); } else { for(long long k=1;ss[k]<=sqrt(z) && p>1;k++) { long long w=0; while(!(p%ss[k])) { p/=ss[k]; w++; } if(w) { change(1,1,n,x,y,k,w); } } if(p>1) { change(1,1,n,x,y,belong[p],1); } } } } }
【NOIP2016提高組A組7.16】第三條跑道