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;
}

 

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