码迷,mamicode.com
首页 > 其他好文 > 详细

【CodeForces】906 D. Power Tower 扩展欧拉定理

时间:2018-04-24 20:27:08      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:欧拉   ret   扩展   计算   var   phi   递归   cal   bad   

【题目】D. Power Tower

【题意】给定长度为n的正整数序列和模数m,q次询问区间[l,r]累乘幂%m的答案。n,q<=10^5,m,ai<=10^9。

【算法】扩展欧拉定理

【题解】扩展欧拉定理的形式:

$$a^b\equiv a^{b\%\varphi(p)+\varphi(p)} \ \ mod \ \ p \ \ (b\leq \varphi(p))$$

特别注意当b<φ(p)且(a,p)≠1时不变

假如现在是三个累乘幂a^(b^c),那么根据扩展欧拉定理:

$$a^{b^c}\ \ mod \ \ p\equiv a^{b^c\%\varphi(p)+\varphi(p)} \ \ mod \ \ p$$

这样我们只需要计算:

$$b^c\ \ mod \ \ \varphi(p)$$

更多个累乘幂的时候只需要不断递归取φ,直至1为止(φ(1)=1)。可以证明至多log(p)次可以得到答案。

这样计算累乘幂的复杂度就是O(log p*log n),也即一次询问的极限复杂度。

这里过程中用到的欧拉函数至多log p个,直接暴力求解,预处理复杂度O(log p*√n),用map存储,实现中可以直接记忆化。

总复杂度O(q*log p*log n)。

技术分享图片
#include<cstdio>
#include<map>
#define ll long long
bool isdigit(char c){return c>=0&&c<=9;}
int read(){
    int s=0,t=1;char c;
    while(!isdigit(c=getchar()))if(c==-)t=-1;
    do{s=s*10+c-0;}while(isdigit(c=getchar()));
    return s*t;
}
using namespace std;
const int maxn=100010;
map<int,int>p;
int a[maxn],n,m,q;
int phi(int n){
    if(p.count(n))return p[n];
    int ans=n,m=n;
    for(int i=2;i*i<=n;i++)if(n!=1&&n%i==0){
        ans=ans/i*(i-1);
        while(n%i==0)n/=i;
    }
    if(n>1)ans=ans/n*(n-1);
    p[m]=ans;
    return ans;
}
int mod(ll x,int y){return x<y?x:x%y+y;}//focus on add,because 2e9*2>int
int power(int x,int k,int m){
    int ans=1;
    while(k){
        if(k&1)ans=mod(1ll*ans*x,m);
        x=mod(1ll*x*x,m);
        k>>=1;
    }
    return ans;
}
int calc(int l,int r,int m){
    if(l==r||m==1)return mod(a[l],m);
    return power(a[l],calc(l+1,r,phi(m)),m);
}    
int main(){
    n=read();m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    q=read();
    while(q--){
        int l=read(),r=read();
        printf("%d\n",calc(l,r,m)%m);
    }
    return 0;
}        
View Code

 

实现:

1.递归过程中直接返回ans+mod,这样下一层就自带+φ(m)了,最后输出答案记得%m就可以了。

2.快速幂过程中的取模改为 int mod(ll x,int y){return x<y?x:x%y+y;} ,这样到某一次数字超过y之后,后面每次都会强制超过y然后+y直至最后一次。

 

【CodeForces】906 D. Power Tower 扩展欧拉定理

标签:欧拉   ret   扩展   计算   var   phi   递归   cal   bad   

原文地址:https://www.cnblogs.com/onioncyc/p/8933040.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!