【JZOJ 4638】 第三条跑道

来源:互联网 发布:云计算 自贸区 编辑:程序博客网 时间:2024/04/28 22:06

Description

这里写图片描述
这里写图片描述
(%%%WerkeyTom_FTD)

Analysis

首先,我们知道,φ(x)=kφ(pakk)
因为ai,x很小,所以可以把他们分解质因数。
600以内的质数只有109个,所以可以开109颗线段树,维护该质数在区间中的指数,乱搞一下。

Code

#include<cstdio>#include<cstring>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)using namespace std;typedef long long ll;const ll N=10010,M=110,mo=1e8+7;ll ind,num,ans,prime[]={1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599};ll n,m,a[M],b[M],c[M][N];struct segment{    ll n,x,lz;}tr[M][N*4];char ch;void read(ll &n){    int t=0,p=1;    for(ch=getchar();ch<'0' || ch>'9';ch=getchar())        if(ch=='-') p=-1;    for(;'0'<=ch && ch<='9';ch=getchar()) t=t*10+ch-'0';    n=t*p;}void pri(ll n,int num){    fo(i,1,109)    {        while(n%prime[i]==0) n/=prime[i],c[i][num]++;        if(n==1) break;    }}void deco(ll n){    m=0;    fo(i,1,109)        if(n%prime[i]==0)        {            a[++m]=i,b[m]=0;            while(n%prime[i]==0) n/=prime[i],b[m]++;        }}ll qmi(ll x,ll n){    ll t=1;    for(;n;n>>=1)    {        if(n&1) t=t*x%mo;        x=x*x%mo;    }    return t;}void up(int k,int v){    tr[k][v].x=tr[k][v+v].x+tr[k][v+v+1].x;    tr[k][v].n=tr[k][v+v].n+tr[k][v+v+1].n;}void build(int k,int v,int l,int r){    if(l==r)    {        tr[k][v].x=c[k][l];        tr[k][v].n=(tr[k][v].x>0);        return;    }    int mid=(l+r)>>1;    build(k,v+v,l,mid);    build(k,v+v+1,mid+1,r);    up(k,v);}void update(segment &a,ll len,ll z){    a.x+=len*z;    a.lz+=z;    a.n=len;}void down(int k,int v,int l,int r){    if(!tr[k][v].lz) return;    int mid=(l+r)>>1;    update(tr[k][v+v],mid-l+1,tr[k][v].lz);    update(tr[k][v+v+1],r-mid,tr[k][v].lz);    tr[k][v].lz=0;}void change(int k,int v,int l,int r,int x,int y,ll z){    if(l==x && r==y)    {        update(tr[k][v],r-l+1,z);        return;    }    down(k,v,l,r);    int mid=(l+r)>>1;    if(y<=mid) change(k,v+v,l,mid,x,y,z);    else    if(x>mid) change(k,v+v+1,mid+1,r,x,y,z);    else change(k,v+v,l,mid,x,mid,z),change(k,v+v+1,mid+1,r,mid+1,y,z);    up(k,v);}void query(int k,int v,int l,int r,int x,int y){    if(l==x && r==y)    {        ind+=tr[k][v].x;        num+=tr[k][v].n;        return;    }    down(k,v,l,r);    int mid=(l+r)>>1;    if(y<=mid) query(k,v+v,l,mid,x,y);    else    if(x>mid) query(k,v+v+1,mid+1,r,x,y);    else    query(k,v+v,l,mid,x,mid),query(k,v+v+1,mid+1,r,mid+1,y);}int main(){    ll _,tp,l,r,x;    read(n);    fo(i,1,n)    {        read(x);        pri(x,i);    }    fo(i,1,109) build(i,1,1,n);    read(_);    while(_--)    {        read(tp),read(l),read(r);        if(!tp)        {            read(x);            deco(x);            fo(i,1,m) change(a[i],1,1,n,l,r,b[i]);        }        else        {            ans=1;            fo(i,1,109)            {                ind=num=0;                query(i,1,1,n,l,r);                ans=ans*qmi(prime[i],ind-num)%mo*qmi(prime[i]-1,num)%mo;            }            printf("%lld\n",ans);        }    }    return 0;}
0 0
原创粉丝点击