2019南京網絡賽-B-super_log(歐拉降冪)

題目鏈接

題意

求冪塔函數,b個a mod m .

擴展歐拉定理

歐拉定理概念

代碼參考

理解:這兩種情況必須要分,但是特例很少,所以很多代碼沒有考慮到第二種情況(B>=phi(C))但是仍然可以過,應該是數據水,沒有特例的情況,也可能不會出現特例??

比如 6^1 % 2560 = 6 , 6^ (1+phi(2560))  %2560   =>  6^1025 =  4096  ,2560的歐拉值是1024,小於1025,所以這就是第二種情況的一個特例。但是很多其他的都符合,不過考慮加上phi(C). 用指數循環節理解:在開頭一部分,比較特殊,在之後纔有循環,但是開頭的這個並不一定是按照循環來的,所以開頭的和後面循環的不一定相等(但是大多數情況都是相等的,只有少數特例),所以纔有上述公式的兩種情況,表示循環節前的和循環節。

求歐拉函數模板

打表,用於處理多個數據,數據範圍最大大概爲5億(一維數組大小)

ll phi[N],prime[N];
ll tot;
void init(){
    phi[1]=1;
    for(ll i=2;i<N;i++){
        if(!phi[i]){
            phi[i]=i-1;
            prime[tot++]=i;
        }
        for(ll j=0;j<tot && i*prime[j]<N;j++){
            if(i%prime[j]) phi[i*prime[j]] = phi[i]*(prime[j]-1);
            else{
                phi[i*prime[j]] = phi[i]*prime[j];
                break;
            }
        }
    }
}

單次計算,如果多次計算,每次都要重複計算,但是可以處理很大到long long 的數據

ll phi(ll n)
{
    ll k = (ll)sqrt(n+0.5);
    ll ans = n;
    for(int i=2;i<=k;i++) {
        if(n%i==0){
            ans = ans/i*(i-1);
            while(n%i==0) n /= i;
        }
    }
    if(n>1) ans = ans/n*(n - 1);
    return ans;
}

歐拉降冪

有一種黑科技可以不用考慮B和phi(C)的比較  ,用一個自定義的MOD函數可以迴避這種比較討論,黑科技證明

ll MOD(ll x,ll m)
{
	return x>m?x%m+m:x;
}
ll Pow(ll x,ll y,ll m)
{
	ll ans=1;
	while(y){
		if(y&1) ans = MOD(ans*x,m);
		x = MOD(x*x,m);
		y >>= 1;
	}
	return ans;
}

用了自定義的MOD之後,需要注意的是當取模的數p,if(p==1)return a;  不是返回0。有很多其他的降冪都是寫的返回0,但是在其他的地方分類比較了,但感覺更多的是因爲數據水?歐拉定理對不互質的兩種情況的公式,很多博客的代碼都是迴避的,也就是直接用快速冪,沒有考慮取模的是大於phi還是小於phi,但是都能AC.


#include <bits/stdc++.h>
using namespace std;
#define N 1000010

typedef long long ll;

ll phi[N],prime[N];
ll tot;
void init(){
    phi[1]=1;
    for(ll i=2;i<N;i++){
        if(!phi[i]){
            phi[i]=i-1;
            prime[tot++]=i;
        }
        for(ll j=0;j<tot && i*prime[j]<N;j++){
            if(i%prime[j]) phi[i*prime[j]] = phi[i]*(prime[j]-1);
            else{
                phi[i*prime[j]] = phi[i]*prime[j];
                break;
            }
        }
    }
}

ll MOD(ll x,ll m)
{
	return x>m ? x%m+m : x;
}
ll Pow(ll x,ll y,ll m)
{
	ll ans=1;
	while(y){
		if(y&1) ans = MOD(ans*x,m);
		x = MOD(x*x,m);
		y >>= 1;
	}
	return ans;
}

ll solve(ll a,ll b,ll p){
	if(p==1)return a;
	if(b==0)return 1;
	ll P=solve(a,b-1,phi[p]);
	return Pow(a,P,p);
}

int main()
{
	init();
	int t;scanf("%d",&t);
	while(t--){
		ll a,b,mod;
		scanf("%lld%lld%lld",&a,&b,&mod);
		ll ans = solve(a,b,mod);
		printf("%lld\n",ans%mod);
	}
	return 0;
}

 

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