計蒜客 Exponial (尤拉降冪)
阿新 • • 發佈:2019-01-08
題意:給出一個n(1~1e9),m(1~1e9),求exponial(n)%m的值
解法:有這樣一個尤拉降冪的公式
(phi(x)表示x的尤拉值)
從n向1來DFS,在中間求冪時使用快速冪取膜然後就可以算出答案了~
尤拉函式:
對一個正整數N,尤拉函式是小於N且與N互質的數的個數.。
例如φ(24)=8,因為1, 5, 7, 11, 13, 17, 19, 23均和 24 互質。
φ(n) =
φ(24)==8.
程式碼如下:
#include<iostream> #include<cstring> #include<string> #include<cstdio> #include<cmath> #include<vector> #include<queue> #include<map> #include<algorithm> using namespace std; const int maxn = 1e5 + 500; #define inf 0x3f3f3f3f #define ll long long ll biao[] = { 0,1,2,9,(1 << 18) };//題目給出的式子的n<=4的結果值 ll mod_pow(ll a, ll n, ll mod) {//快速冪 a %= mod; ll ret = 1; while (n) { if (n & 1) ret = (ret*a) % mod; a = a*a%mod; n >>= 1; } return ret; } ll euler(ll n) { //log(n)時間內求一個數的尤拉值 ll ans = n; for (ll i = 2; i*i <= n; i++) { if (n%i == 0) { ans -= ans / i; while (n%i == 0) n /= i; } } if (n>1) ans -= ans / n; return ans; } ll dfs(ll n, ll m) { if (m == 1) return 1; if (n <= 4) //因為當n<=4時才有可能出現冪小於等於模數的情況,其餘時候都是冪大於模數 { //所以預處理出n的最小4項結果,第5項已經遠大於模數的最大值1e9了 if (biao[n] >= m) return biao[n] % m + m; return biao[n]; } ll exp = dfs(n - 1, euler(m)); return mod_pow(n, exp, m) + m; } int main() { ll n, mod; while (~scanf("%lld%lld", &n, &mod)) { ll exp = dfs(n - 1, euler(mod)); ll ans = mod_pow(n, exp, mod); printf("%lld\n", ans); } }