第一场-E - Exponial

题目链接:点击打开链接

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:

  • Factorials: 2016!=2016 ⋅ 2015 ⋅ ... ⋅ 2 ⋅ 1.

Illustration of exponial(3) (not to scale), Picture by C.M. de Talleyrand-Périgord via Wikimedia Commons

In this problem we look at their lesser-known love-child the exponial, which is an operation defined for all positive integers n as 
exponial(n)=n(n − 1)(n − 2)21
For example, exponial(1)=1 and exponial(5)=54321 ≈ 6.206 ⋅ 10183230 which is already pretty big. Note that exponentiation is right-associative: abc = a(bc).

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).

Input

There will be several test cases. For the each case, the input consists of two integers n (1 ≤ n ≤ 109) and m (1 ≤ m ≤ 109).

Output

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

Sample Input

2 42
5 123456789
94 265

Sample Output

2
16317634
39
(一)题目大意:给定n,m,求数:n^((n-1)^((n-2)^...^1))%m,其中n,m<=1e9;

(二)解题思路:

  1. 直接快速幂的复杂度为O(CN)的,显然不行。
  2. 数学题目做得少,其实没有什么太多好说的,这个题就是考了一欧拉降幂公式(具体的证明过程请移步百度或Wiki^_^):


其中的ψ()为欧拉函数(不懂的话同上)。

        3.我们可以发现每次我们可以将模数由C降为ψ(C),这里不加证明地给出结论,这个降地速度是log级别的,而当模数为1时,结果当然就是0,所以我们按照以上式子递归求解即可得到结果。注意一点的是上式成立的条件为A^B(A的B次方)>C(?),所以应当预处理出n<=4时的结果。

(三)具体代码:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#define LL long long
using namespace std;
LL know[]={1,1,2,9,262144};
LL phi(LL n){
    LL res=n,m=n;
    for(int i=2;i*i<=n;i++){
        if(m%i==0){
            res-=res/i;
            while(m%i==0)m/=i;
        }
    }
    if(m>1)res-=res/m;
    return res;
}
LL ksm(LL a,LL b,LL mod){
    LL res=1;
    while(b){
        if(b&1)res=res*a%mod;
        b>>=1;a=a*a%mod;
    }
    return res;
}
LL solve(LL n,LL mod){
    if(mod==1)return 0;
    if(n<=4)return know[n]%mod;
    LL PHI=phi(mod);
    LL Next=solve(n-1,PHI);
    return ksm(n,Next+PHI,mod);
}
int main(){
    freopen("in.txt","r",stdin);
    LL n,m;
    while(cin>>n>>m){cout<<solve(n,m)<<endl;}
    return 0;
}

表示数学是真的神奇!!!

猜你喜欢

转载自blog.csdn.net/xbb224007/article/details/79867454