Exponial欧拉降幂

时间限制: 1 Sec  内存限制: 64 MB
提交: 255  解决: 67
[提交] [状态] [讨论版] [命题人:外部导入]

题目描述

Illustration of exponial(3) (not to scale), Picture by C.M. de Talleyrand-Périgord via Wikimedia Commons Everybody loves big numbers (if you do not, you might want to stop reading at this point). There are many ways of constructing really big numbers known to humankind, for instance:

In this problem we look at their lesser-known love-child the exponial , which is an operation defined for all positive integers n as

For example, exponial(1) = 1 and  which is already pretty big. Note that exponentiation is right-associative:  .
Since the exponials are really big, they can be a bit unwieldy to work with. Therefore we would like you to write a program which computes exponial(n) mod m (the remainder of exponial(n) when dividing by m).

输入

The input consists of two integers n (1 ≤ n ≤ 109 ) and m (1 ≤ m ≤ 109 ).

输出

Output a single integer, the value of exponial(n) mod m.

样例输入

2 42

样例输出

2

弄懂了,这个是欧拉降幂,两种条件

那么,简单举个3个次方叠加的例子

要想求a^{b^{c}}%P,因为是从上向下求的,所以要先求b^{c},那么

\begin{cases} a^{b^{c}}mod(p)=a^{b^{c}mod(phi(p))+phi(p)},b^{c}>=phi(p)\\ a^{b^{c}}mod(p)=a^{b^{c}mod(phi(p))},b^{c}<phi(p) \end{cases}

那么递归的时候显然下一次的p就是这次的phi(p),

也就是说

\begin{cases} b^{c}mod(p)=b^{c}mod(p)+p,b^{c}>=p\\ b^{c}mod(p)=b^{c}mod(p),b^{c}<p \end{cases}

那么就显然了,在取模的时候进行变换就好了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll> mp;
ll phi(ll k){
    ll i,s=k,x=k;
    if (mp.count(k)) return mp[x];
    for(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);
    mp[x]=s; return s;
}
ll Pow(ll a,ll b,ll c){
    ll ans = 1;
    a = a<c?a:a%c+c;
    while(b){
        if(b&1) ans = ans*a<c?ans*a:ans*a%c+c;
        a = a*a<c?a*a:a*a%c+c;
        b>>=1;
    }
    return ans<c?ans:ans%c+c;
}
ll Euler(ll a,ll c){
    if(a==1||c==1) return a<c?a:a%c+c;
    return Pow(a,Euler(a-1,phi(c)),c);
}
int main()
{
    ll a,b;
    cin>>a>>b;
    cout<<Euler(a,b)%b<<endl;
    return 0;
}

代码是根据网上某个cf题解代码改的,我还是有点迷糊

#include<bits/stdc++.h>
#define ll long long
#define Mod(a,b) a<b?a:a%b+b
using namespace std;
ll n,q,mod;
map<ll,ll> mp;
ll qpow(ll x,ll n,ll mod){
    ll res=1;
    while(n){
        if (n&1) res=Mod(res*x,mod),n--;
        x=Mod(x*x,mod); n>>=1;
    }
    return res;
}
ll phi(ll k){
    ll i,s=k,x=k;
    if (mp.count(k)) return mp[x];
    for(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);
    mp[x]=s; return s;
}
ll Eu(ll a,ll c){
    if (a==1||c==1) return Mod(a,c);
    return qpow(a,Eu(a-1,phi(c)),c);
}
int main(){
    scanf("%lld%lld",&n,&mod);

    printf("%lld\n",Eu(n,mod)%mod);

    return 0;
}

另一种不太清楚的操作

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
 
ll phi(ll x)
{
    ll res = x,a = x;
    for(int i=2;i*i<=a;i++)
    {
        if(a%i==0)
        {
            res = res/i*(i-1);//res -= res/i;
            while(a%i==0)a/=i;
        }
    }
    if(a>1)res =res/a*(a-1);//res -= res/a;
    return res;
}
 
ll qpow(ll a,ll b,ll m)
{
    ll ans=1;
    a%=m;
    while(b)
    {
        if(b&1)
            ans=ans*a%m;
        a=(a*a)%m;
        b/=2;
    }
    return ans;
}
 
 
ll solve(ll n,ll m)
{
    if(m==1) return 0LL;
    if(n==1) return 1LL;
    if(n==2) return 2LL%m;
    if(n==3) return 9LL%m;
    if(n==4) return qpow(4,9,m);
 
    ll oula=phi(m);
    ll t=solve(n-1,oula);
    ll ans=qpow(n,oula+t,m);
    return ans;
}
 
int main()
{
    ll n,m;
    scanf("%lld%lld",&n,&m);
 
    printf("%lld\n",solve(n,m));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Du_Mingm/article/details/82956406