P5091 【模板】欧拉定理

\(\color{#0066ff}{ 题目描述 }\)

给你三个正整数,\(a,m,b\),你需要求: \(a^b \mod m\)

\(\color{#0066ff}{输入格式}\)

一行三个整数,\(a,m,b\)

\(\color{#0066ff}{输出格式}\)

一个整数表示答案

\(\color{#0066ff}{输入样例}\)

2 7 4
    
998244353 12345 98765472103312450233333333333

\(\color{#0066ff}{输出样例}\)

2
    
5333

\(\color{#0066ff}{数据范围与提示}\)

注意输入格式,\(a,m,b\) 依次代表的是底数、模数和次数

样例1解释:
\(2^4 \mod 7 = 2\)
输出2

数据范围:
对于全部数据:
\(1≤a≤10^9\)
\(1≤b≤10^{20000000}\)
\(1≤m≤10^6\)

\(\color{#0066ff}{ 题解 }\)

其实就一个式子。。。

\[\left\{\begin{aligned}a^b \equiv a^b \mod m \ \ \ \ \ b < \varphi(m) \\ a^b\equiv a^{b \ mod\ \varphi(m)+\varphi(m)} b\ge\varphi(m)\end{aligned}\right. \]

#include<bits/stdc++.h>
#define LL long long
LL in() {
	char ch; LL x = 0, f = 1;
	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
	return x * f;
}
LL ksm(LL x, LL y, LL mod) {
	if(x == 0) return 0;
	LL re = 1LL;
	while(y) {
		if(y & 1) re = re * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return re;
}
int getphi(int x) {
	int res = x;
	int phi = x;
	for(int i = 2; i * i <= x; i++) {
		if(res % i == 0) {
			while(res % i == 0) res /= i;
			phi = phi / i * (i - 1);
		}
	}
	if(res > 1) phi = phi / res * (res - 1);
	return phi;
}
int main() {
	LL a = in(), m, b;
	LL phi = getphi(m = in());
	char ch;
	while(!isdigit(ch = getchar()));
	bool flag = false;
	for(b = ch ^ 48; isdigit(ch = getchar()); b = (b << 1LL) + (b << 3LL) + (ch ^ 48)) if(b >= phi) flag = true, b %= phi;
	printf("%lld\n", ksm(a, (flag? b + phi : b), m));
	return 0;
}
posted @ 2019-01-22 20:58  olinr  阅读(185)  评论(0编辑  收藏  举报