尤拉定理
阿新 • • 發佈:2022-05-19
尤拉定理
尤拉定理
\(gcd(a,m)=1\) 時, \(a^{x}\equiv a^{x \mod \phi(m)}\;(mod\;m)\)
擴充套件尤拉定理:
\(a^{x}\equiv a^{x \mod \phi(m)+\phi(m)}\;(mod\;m)\)
證明:
a 與 m 互質時,從 \(a_0\) 就進入迴圈
a 與 m 不互質時,從前 c 項不進入迴圈,設迴圈長度為 L
設已經走了 x 步,則 x = L + x - L 所以先走 L 步進入迴圈,這時再走 x - L 步的位置與再走 (x - L) % L 一樣,因此有
(L + (x - L) % L) = L + x % L, 即 \(a^{x}\equiv a^{x \mod \phi(m)+\phi(m)}\;(mod\;m)\)
BZOJ 3884, 上帝與集合的正確用法 - 題目 - Daimayuan Online Judge
\(\phi (m)\) 的性質
-
\(\phi(m)\) 為偶數(除 m = 2 外)
-
\(\phi(m)<=\frac m2\)
因此只需 log p 次就可將 p 減為 1,因此只需遞迴子問題 log p 次即可
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> using namespace std; typedef long long ll; ll qmi(ll a, ll b, ll p) { ll ans = 1; while(b) { if (b & 1) ans = ans * a % p; a = a * a % p; b >>= 1; } return ans % p; } //遞迴子問題求解 ll calc(int p) { if (p == 1) return 0; ll phip = p, now = p; for (int i = 2; i <= now / i; i++) { if (now % i) continue; phip = phip / i * (i - 1); while(now % i == 0) now /= i; } if (now > 1) phip = phip / now * (now - 1); ll ans = calc(phip); return qmi(2, ans + phip, p); } ll solve() { int p; cin >> p; return calc(p); } int main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int T; cin >> T; while(T--) cout << solve() << endl; return 0; }
CF Round #454(Div 1) D, Power Tower - 題目 - Daimayuan Online Judge
使用擴充套件尤拉定理降冪時,重定義 mod 運算為
ll mod(ll a, ll b)
{
if (a < b) return a;
return a % b + b;
}
#include <iostream> #include <cstring> #include <algorithm> #include <vector> #include <cmath> #include <map> using namespace std; typedef long long ll; const int N = 1e5 + 10; ll a[N]; map<ll, ll> mp; //使用擴充套件尤拉定理時要重定義mod ll mod(ll a, ll b) { if (a < b) return a; return a % b + b; } ll qmi(ll a, ll b, ll p) { ll ans = 1; while(b) { if (b & 1) ans = mod(ans * a, p); b >>= 1; a = mod(a * a, p); } return mod(ans, p); } ll phi(ll x) { if (mp[x]) return mp[x]; ll now = x, ans = x; for (int i = 2; i <= now / i; i++) { if (now % i == 0) ans -= ans / i; while(now % i == 0) now /= i; } if (now > 1) ans -= ans / now; return mp[x] = ans; } ll solve(int l, int r, int p) { if (p == 1 || l == r) return mod(a[l], p); return qmi(a[l], solve(l+1, r, phi(p)), p); } int main() { int n, m, q; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%lld", a + i); scanf("%d", &q); while(q--) { int l, r; scanf("%d%d", &l, &r); printf("%lld\n", solve(l, r, m) % m); } return 0; }