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

【题目】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;
}        

实现:

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

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

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

时间: 2024-07-30 16:56:42

【CodeForces】906 D. Power Tower 扩展欧拉定理的相关文章

CodeForces 907F Power Tower(扩展欧拉定理)

Priests of the Quetzalcoatl cult want to build a tower to represent a power of their god. Tower is usually made of power-charged rocks. It is built with the help of rare magic by levitating the current top of tower and adding rocks at its bottom. If

[CodeForces - 906D] Power Tower——扩展欧拉定理

题意 给你 $n$ 个数 $w$ 和一个数 $p$,$q$个询问,每次询问一个区间 $[l,r] $,求 $w_l^{(w_{l+1}^{(w_{l+2}…^{w_r})})}\mod p$. 分析 由扩展欧拉定理: $$a^b\equiv \begin{cases} a^{b\%\phi(p)}~~~~~~~~~~~gcd(a,p)=1\\ a^b~~~~~~~~~~~~~~~~~~gcd(a,p)\neq1,b<\phi(p)\\ a^{b\%\phi(p)+\phi(p)}~~~~gcd(

Codeforces 906 D Power Tower

Discription Priests of the Quetzalcoatl cult want to build a tower to represent a power of their god. Tower is usually made of power-charged rocks. It is built with the help of rare magic by levitating the current top of tower and adding rocks at its

Codeforces 906D Power Tower(欧拉函数 + 欧拉公式)

题目链接  Power Tower 题意  给定一个序列,每次给定$l, r$ 求$w_{l}^{w_{l+1}^{w_{l+2}^{...^{w_{r}}}}}$  对m取模的值 根据这个公式 每次递归计算. 因为欧拉函数不断迭代,下降到$1$的级别大概是$log(m)$的,那么对于每一次询问最多需要递归$log(m)$次 注意每次求解欧拉函数的时候要用map存下来,方便以后查询 #include <bits/stdc++.h> using namespace std; #define re

【CF906D】Power Tower

题目 题目链接:https://codeforces.com/problemset/problem/906/D 给出一个数列 \(a\),每次询问给出 \(l,r\),求 思路 根据扩展欧拉定理,当 \(b\geq \varphi(p)\) 时, \[a^b\equiv a^{b\bmod \varphi(p)+\varphi(p)}\pmod p \] 所以我们可以考虑递归求解,类似 这题,直到 \(l>r\) 或 \(p=1\). 由于 \(\varphi(\varphi(n))...\)

小学扩展欧拉定理

学了一下扩展欧拉定理,不会证,记了个结论,笔记的话,随便去网上搜一搜吧.-bzoj3884:上帝与集合的正确用法无脑板子题额 #include <cstdio> #include <cstring> #include <algorithm> typedef long long LL; inline int Pow(int x,int y,int P){ int ret=1; while(y){ if(y&1)ret=(LL)ret*x%P; x=(LL)x*x%

[luogu4139]上帝与集合的正确用法【欧拉定理+扩展欧拉定理】

题目大意 让你求\(2^{2^{2^{\cdots}}}(mod)P\)的值. 前置知识 知识1:无限次幂怎么解决 让我们先来看一道全国数学竞赛的一道水题: 让你求解:\(x^{x^{x^{\cdots}}}=2\)方程的解. 对于上面的无限次幂,我们可以把这个式子移上去,得到了\(x^{2}=2\). 因为指数的原因,所以我们可以直接得到了\(x=\sqrt{2}\). 以上的问题,启示我们对于这一些无限次幂可以转移来解决. 以上的东西可能用不到 知识2:欧拉定理和扩展欧拉定理 详细请出门左拐

[BZOJ 4869][SXOI2017]相逢是问候(扩展欧拉定理+线段树)

Description Informatik verbindet dich und mich. 信息将你我连结.B君希望以维护一个长度为n的数组,这个数组的下标为从1到n的正整数.一共有m个操作,可以 分为两种:0 l r表示将第l个到第r个数(al,al+1,...,ar)中的每一个数ai替换为c^ai,即c的ai次方,其中c是 输入的一个常数,也就是执行赋值ai=c^ai1 l r求第l个到第r个数的和,也就是输出:sigma(ai),l<=i<=rai因为 这个结果可能会很大,所以你只需

[BZOJ 3884]上帝与集合的正确用法(扩展欧拉定理)

Description 根据一些书上的记载,上帝的一次失败的创世经历是这样的: 第一天, 上帝创造了一个世界的基本元素,称做“元”. 第二天, 上帝创造了一个新的元素,称作“α”.“α”被定义为“元”构成的集合.容易发现,一共有两种不同的“α”. 第三天, 上帝又创造了一个新的元素,称作“β”.“β”被定义为“α”构成的集合.容易发现,一共有四种不同的“β”. 第四天, 上帝创造了新的元素“γ”,“γ”被定义为“β”的集合.显然,一共会有16种不同的“γ”. 如果按照这样下去,上帝创造的第四种元