P3747 [6つの省試験2017]再会の挨拶

問題の意味

オペランドのいずれかが\(K \)時間は、その後数となる\(C ^ C ^ {{...}}} ^ {a_iを\) ここで\(C \)有している\(K \) A。

よると、適切な使用P4139神との集まり、この質問、私たちは、についての彼らの継続的なオイラー関数への変更の数を見ることができます(\ログ)\倍以上となり、アナログの任意の数(\ 1)\です\(0 \) 我々は潜在的なツリーラインを解決することができますので。

同じの弾性率があるため、私たちは事前にすべてのことができるように\(\ varphi(\ varphi(... \ varphi(P-)...))\) セグメントツリー操作の数を記録した後。

これは、3 \(ログ\) でも高速電力ので、できる各\(\ varphi(\ varphi( ... \ varphi(P)...))\) 光の速度とパワーの前処理、解決しました。

なお、拡張中国の剰余定理\(a_k \当量A ^ { K \%\ varphi(P)+ \ varphi(P)} \ PMOD {P}は\) 適用場合にのみ\(K \ geqslant \ varphi( P )\)評価するときに我々が使用して、\(フラグ\)したいかどうかを示します\(+ \ varphi(P-))\

コード:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
const int maxn=50010;
const int maxt=10010;
int n,m,mod,C,maxtim;
int a[maxn];
int pw1[60][maxt],pw2[60][maxt];
bool flag;
bool flag1[60][maxt],flag2[60][maxt];
vector<int>ve;
struct Seg
{
    #define sum(p) (seg[p].sum)
    #define cnt(p) (seg[p].cnt)
    int sum,cnt;
}seg[maxn<<2];
inline int read()
{
    char c=getchar();int res=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    return res*f;
}
inline int phi(int x)
{
    int res=x,tmp=x;
    for(int i=2;i*i<=tmp;i++)
    {
        if(tmp%i)continue;
        res=res/i*(i-1);
        while(tmp%i==0)tmp/=i;
    }
    if(tmp>1)res=res/tmp*(tmp-1);
    return res;
}
inline void pre_work()
{
    int tmp=mod;
    ve.push_back(mod);
    while(tmp>1)tmp=phi(tmp),ve.push_back(tmp);
    ve.push_back(1);
    for(unsigned int i=0;i<ve.size();i++)
    {
        pw1[i][0]=1;
        for(int j=1;j<=10000;j++)
        {
            pw1[i][j]=pw1[i][j-1]*C;
            if(pw1[i][j]>=ve[i])pw1[i][j]%=ve[i],flag1[i][j]=1;
            flag1[i][j]|=flag1[i][j-1];
        }
    }
    for(unsigned int i=0;i<ve.size();i++)
    {
        pw2[i][0]=1;flag2[i][1]=flag1[i][10000];
        for(int j=1;j<=10000;j++)
        {
            pw2[i][j]=pw2[i][j-1]*pw1[i][10000];
            if(pw2[i][j]>=ve[i])pw2[i][j]%=ve[i],flag2[i][j]=1;
            flag2[i][j]|=flag2[i][j-1];
        }
    }
}
inline void up(int p)
{
    sum(p)=(sum(ls(p))+sum(rs(p)))%mod;
    cnt(p)=min(cnt(ls(p)),cnt(rs(p)));
}
void build(int p,int l,int r)
{
    if(l==r){sum(p)=a[l];return;}
    int mid=(l+r)>>1;
    build(ls(p),l,mid);build(rs(p),mid+1,r);
    up(p);
}
inline int power(int x,int id)
{
    flag=0;
    int res=pw1[id][x%10000]*pw2[id][x/10000];
    if(res>=ve[id])res%=ve[id],flag=1;
    flag|=flag1[id][x%10000]|flag2[id][x/10000];
    return res;
}
int calc(int x,int dep,int k)
{
    flag=0;
    if(dep==k)
    {
        if(x>=ve[dep])flag=1,x%=ve[dep];
        return x;
    }
    int tmp=calc(x,dep+1,k);
    return power(flag?tmp+ve[dep+1]:tmp,dep);
}
void change(int p,int l,int r,int ql,int qr)
{
    if(cnt(p)>=(int)ve.size()-1)return;
    if(l==r)
    {
        cnt(p)++;
        sum(p)=calc(a[l],0,cnt(p));
        return;
    }
    int mid=(l+r)>>1;
    if(ql<=mid)change(ls(p),l,mid,ql,qr);
    if(qr>mid)change(rs(p),mid+1,r,ql,qr);
    up(p);
}
int query(int p,int l,int r,int ql,int qr)
{
    if(l>=ql&&r<=qr)return sum(p);
    int mid=(l+r)>>1,res=0;
    if(ql<=mid)res=(res+query(ls(p),l,mid,ql,qr))%mod;
    if(qr>mid)res=(res+query(rs(p),mid+1,r,ql,qr))%mod;
    return res;
}
signed main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout); 
    n=read();m=read();mod=read();C=read();
    for(int i=1;i<=n;i++)a[i]=read();
    build(1,1,n);
    pre_work();
    for(int i=1;i<=m;i++)
    {
        int op=read(),l=read(),r=read();
        if(!op)change(1,1,n,l,r);
        else printf("%lld\n",query(1,1,n,l,r)); 
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/nofind/p/12078423.html