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
using namespace std;
typedef long long ll;
map 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>=1;
    }
    return ans>a>>b;
    cout<

 

 

 

 

 

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

 

#include
#define ll long long
#define Mod(a,b) a 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
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;
}

 

你可能感兴趣的:(模板类(什么,这也是模板),规律题(找啊,找啊,找不着啊),思维(抖啊,抖啊,抖个机灵儿))