CodeForces - 906D Power Tower(欧拉降幂定理)

Power Tower

 CodeForces - 906D 

题目大意:有N个数字,然后给你q个区间,要你求每一个区间中所有的数字从左到右依次垒起来的次方的幂对m取模之后的数字是多少。

用到一个新知识,欧拉降幂定理

记住公式 $\LARGE n^x \equiv n^{\varphi(m)\ +\ x\ mod\ \varphi(m)}(mod\ m)​$这个式子当且仅当x>φ(m)时满足。那么就可以递归求解了。

暂时不太明白怎么证明

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#define maxn 100010
#define Mod(a,b) a<b?a:a%b+b
using namespace std;
long long n,m,a[maxn];
map<long long,long long>p;
long long qread(){
    long long i=0,j=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')j=-1;ch=getchar();}
    while(ch<='9'&&ch>='0')i=i*10+ch-'0',ch=getchar();
    return i*j;
}
long long Pow(long long x,long long y,long long mod){
    long long res=1;
    while(y){
        if(y&1)res=Mod(res*x,mod);
        x=Mod(x*x,mod);
        y>>=1;
    }
    return res;
}
long long phi(long long k){
    long long s=k,x=k;
    if(p[k])return p[k];
    for(long long i=2;i*i<=k;i++){
        if(k%i==0)s=s/i*(i-1);
        while(k%i==0)k/=i;
    }
    if(k>1)s=s/k*(k-1);
    p[x]=s;return s;
}
long long solve(int l,int r,long long mod){
    if(l==r||mod==1)return Mod(a[l],mod);
    return Pow(a[l],solve(l+1,r,phi(mod)),mod);
}
int main(){
    freopen("Cola.txt","r",stdin);
    n=qread();m=qread();
    for(int i=1;i<=n;i++)a[i]=qread();
    int Q;scanf("%d",&Q);
    int l,r;
    while(Q--){
        scanf("%d%d",&l,&r);
        cout<<solve(l,r,m)%m<<endl;
    }
    return 0;
}

 



posted @ 2018-01-12 15:50  Echo宝贝儿  阅读(735)  评论(0编辑  收藏  举报