The Preliminary Contest for ICPC Asia Nanjing 2019 B. super_log 欧拉降幂

题意:求(a^a)^a.....(b个a)mod m的结果

题解:跟bzoj 3884 欧拉降幂那题是一样的,但是这题大家都写的超级别扭.....,这题因为要判断幂次是不是大于Phi(大于的话就需要+phi)所以不能往下传值,因为计算幂次会爆。。只能往上传值,这样导致的结果就是需要变动快速幂来判断是不是大于,如果大于的话就往上多传一个phi

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define mem(s) memset(s, 0, sizeof(s))
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
const int maxn = 1e6+5;
const int mod = 998244353;
ll eular(ll n)
{
    ll ans = n;
    for(int i = 2; i*i <= n; i++)
    {
        if(n % i == 0)
        {
            ans -= ans/i; //等价于通项,把n乘进去
            while(n % i == 0) //确保下一个i是n的素因数
                n /= i;
        }
    }
    if(n > 1)ans -= ans/n; //最后可能还剩下一个素因数没有除
    return ans;
}
ll quick_pow(ll a,ll b,ll m){
	ll ans=1,flag=0;
	while(b){
		if(b&1){
			ans=ans*a;
			if(ans>=m)flag=1,ans%=m;
		}
		b>>=1;if(!b)break;//这一步要注意,要提前退出,不然a*a有可能会没乘到ans上却被判断了
		a=a*a;
		if(a>=m)flag=1,a%=m;
		//b>>=1;
	}
	return flag?ans%m+m:ans%m;
}
ll f(ll a,ll b,ll p){
	if(b==1||p==1)return a<p?a%p:a%p+p;
	int k=eular(p);
	return quick_pow(a,f(a,b-1,k),p);
}
int main() 
{
	int t;
	cin>>t;
	while(t--){
		ll a,b,p;
		cin>>a>>b>>p;
		if(b==0)cout<<1%p<<endl;
		else cout<<f(a,b,p)%p<<endl;
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章