• 【洛谷3934】[Ynoi2016] 炸脖龙 I(奈芙莲树)


    题目链接

    • 给定一个长度为 \(n\) 的序列。\(q\) 次操作,分为两种:给区间 \([l,r]\) 加上一个数 \(v\);对区间 \([l,r]\) 询问 \(a_l^{a_{l+1}^{\ \cdots\ ^{a_r}}}\operatorname{mod}p\)
    • \(1\le n,q\le5\times10^5\)\(1\le p\le2\times10^7\)\(1\le a_i\le2\times10^9\)\(0\le v\le2\times10^9\)

    这题的做法因为与此题完全一样的 【洛谷4691】Nephren Ruq Insania 一题而被称作 奈芙莲树,然而似乎奈芙莲树也只能做这一题。。。

    树状数组维护区间加

    对于区间加操作,我们用树状数组维护即可。

    因为在接下来的询问过程中我们只会涉及到单点求值操作。

    扩展欧拉定理

    对于任意模数 \(p\),都有:

    \[a^x\equiv \begin{cases} a^x&x < \phi(p),\\ a^{x\operatorname{mod}\phi(p)+\phi(p)}&x\ge\phi(p) \end{cases} (\operatorname{mod}p) \]

    由于 \(p\) 在取至多 \(\log\)\(\phi(p)\) 后就会变成 \(1\),而任意数模 \(1\) 都为 \(0\),我们可以直接暴力计算。

    但扩展欧拉定理最麻烦的一点就是讨论指数是否大于等于 \(\phi(p)\)

    首先,如果区间中存在某个位置 \(t\) 满足 \(a_t=1\),因为 \(1\) 的任意次方都为 \(1\),所以我们可以直接把 \(r\) 设为 \(t\)。那么现在 \([l,r)\) 中的数都非 \(1\) 了。

    又由于 \(2^{2^{2^{2^2}}}\) 已经大于 \(p\) 的上界了,所以这样一来只要运算五位就肯定会超出 \(\phi(p)\),而既然至多只有 \(5\) 位,我们完全可以暴力运算一下,减少讨论。

    如果暴力算出的结果超出 \(\phi(p)\),就递归求解区间 \([l,r]\)\(\phi(p)\) 的答案加上 \(\phi(p)\) 作为指数;如果不超出 \(\phi(p)\) 说明剩余区间不到 \(5\) 位,且当前求出的就是剩余区间的值,直接作为指数即可。

    代码:\(O(n\log^2 p)\)

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Rg register
    #define RI Rg int
    #define Cn const
    #define CI Cn int&
    #define I inline
    #define W while
    #define N 500000
    #define SZ 20000000
    #define V(i) (a[i]+T.Q(i))
    #define LL long long
    using namespace std;
    int n,a[N+5];set<int> S;set<int>::iterator it,jt;
    I int QP(RI x,LL y,CI p) {RI t=1;W(y) y&1&&(t=1LL*t*x%p),x=1LL*x*x%p,y>>=1;return t;}
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    	int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    	Tp I void writeln(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc('\n');}
    }using namespace FastIO;
    int Pt,P[SZ+5],phi[SZ+5];I void Sieve()//线性筛预处理欧拉函数
    {
    	phi[1]=1;for(RI i=2,j;i<=SZ;++i) for(!P[i]&&(phi[P[++Pt]=i]=i-1),j=1;i*P[j]<=SZ;++j)
    		if(P[i*P[j]]=1,i%P[j]) phi[i*P[j]]=phi[i]*(P[j]-1);else {phi[i*P[j]]=phi[i]*P[j];break;}
    }
    struct TreeArray//树状数组维护区间加
    {
    	LL a[N+5];I void U(RI x,CI v) {W(x<=n) a[x]+=v,x+=x&-x;}I LL Q(RI x) {LL t=0;W(x) t+=a[x],x-=x&-x;return t;}
    	I void U(CI l,CI r,CI v) {U(l,v),U(r+1,-v);}
    }T;
    I int Q(CI l,CI r,CI p)//询问[l,r]模p的答案
    {
    	RI v=V(l)%p;if(!v) return 0;if(l==r) return v;RI m=min(l+5,r),t=phi[p];LL o,x=V(m),y;
    	for(RI i=m-1;i^l;--i) {y=x,x=1,o=V(i);W(y--) if(1.0L*x*o>t) return QP(v,Q(l+1,r,t)+t,p);else x*=o;}return QP(v,x,p);//暴力算5位,如果过程中超出φ(p)就递归询问,否则直接作为模数
    }
    int main()
    {
    	RI Qt,i,op,x,y,z,t;for(read(n,Qt),Sieve(),i=1;i<=n;++i) read(a[i]),a[i]==1&&(S.insert(i),0);W(Qt--)
    	{
    		if(read(op,x,y,z),op==1) {z&&(S.erase(S.lower_bound(x),S.upper_bound(y)),T.U(x,y,z),0);continue;}
    		S.lower_bound(x)!=S.end()&&(y=min(y,*S.lower_bound(x))),writeln(Q(x,y,z)%z);//将右端点与区间中第一个1的位置取min
    	}return clear(),0;
    }
    
  • 相关阅读:
    AOP与IOC的概念(即spring的核心)
    Md5密码加密的使用
    all-mobile.js
    config.js
    login.css
    template.css
    index.js
    view.js
    admin.css
    admin.js
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3934.html
Copyright © 2020-2023  润新知