51nod 1642 区间欧拉函数 && codeforce594D REQ
Posted akcqhzdy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1642 区间欧拉函数 && codeforce594D REQ相关的知识,希望对你有一定的参考价值。
画一下柿子就知道是求区间乘积乘区间内所有质因数的(p-1)/p(就是求欧拉的公式嘛)
看上去莫队就很靠谱然而时间O(nsqrt(n)logn)并不资瓷
还是离线,确定右端点,对于1~i的区间内的质因数我们在树状数组把他们插入到最后一次出现的位置,然后扫一次求逆元+找质因数O(nlog^2n)
注意算质因子的时候不能用试除法啊
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const LL mod=1e9+7; int quick_pow(int A,int p) { int ret=1; while(p!=0) { if(p%2==1)ret=(LL)ret*A%mod; A=(LL)A*A%mod;p/=2; } return ret; } int inv(int A){return quick_pow(A,mod-2);} int pr,prime[1100000],pm[1100000]; bool v[1100000]; void get_prime() { pr=0; for(int i=2;i<=1001000;i++) { if(v[i]==false)prime[++pr]=i,pm[i]=i; for(int j=1;j<=pr&&i*prime[j]<=1001000;j++) { v[i*prime[j]]=true; pm[i*prime[j]]=min(pm[i],prime[j]); if(i%prime[j]==0)break; } } } int n;LL s[210000]; int lowbit(int x){return x&-x;} void change(int x,LL k) { while(x<=n) { s[x]=s[x]*k%mod; x+=lowbit(x); } } LL getsum(int x) { LL ret=1; while(x>0) { ret=ret*s[x]%mod; x-=lowbit(x); } return ret; } int a[210000];LL sm[210000]; struct query{int l,r,id;}q[210000];int as[210000]; bool cmp(query q1,query q2){return q1.r<q2.r;} int last[1100000]; int main() { get_prime(); scanf("%d",&n); sm[0]=1; for(int i=1;i<=n;i++) scanf("%d",&a[i]), sm[i]=sm[i-1]*a[i]%mod; int Q; scanf("%d",&Q); for(int i=1;i<=Q;i++) scanf("%d%d",&q[i].l,&q[i].r), q[i].id=i; sort(q+1,q+Q+1,cmp); int j=1; memset(last,0,sizeof(last)); for(int i=1;i<=n;i++)s[i]=1; for(int i=1;i<=n;i++) { int d=a[i]; while(d>1) { int p=pm[d];LL c=(LL)(p-1)*inv(p)%mod; if(last[p]>0)change(last[p],inv(c)); last[p]=i; change(last[p],c); while(d%p==0)d/=p; } while(j<=Q&&q[j].r==i) { as[q[j].id]=sm[q[j].r]*inv(sm[q[j].l-1])%mod*getsum(q[j].r)%mod*inv(getsum(q[j].l-1))%mod; j++; } } for(int i=1;i<=Q;i++)printf("%d ",as[i]); return 0; }
以上是关于51nod 1642 区间欧拉函数 && codeforce594D REQ的主要内容,如果未能解决你的问题,请参考以下文章