好久没写题解了啊……其实我并没有颓废,只是刷树形DP去了
题目描述
给定 a , b , c a,b,c a,b,c,有 a , c ≤ 1 0 9 , b ≤ 1 0 20000000 a,c\leq10^9, b\leq10^{20000000} a,c≤109,b≤1020000000,求 a b   m o d   c a^b\bmod c abmodc
(话说直接做多组数据版就双倍经验了嘛……)
欧拉定理
就是:
a
φ
(
m
)
≡
1
(
m
o
d
m
)
,
(
a
,
m
)
=
1
a^{\varphi(m)}\equiv 1\pmod m,(a,m)=1
aφ(m)≡1(modm),(a,m)=1
欧拉定理可以用于降幂,可以得到
a
b
=
a
b
 
m
o
d
 
φ
(
m
)
+
φ
(
m
)
(
m
o
d
m
)
(
b
≥
m
)
a^b=a^{b\bmod{\varphi(m)}+\varphi(m)}\pmod m(b\geq m)
ab=abmodφ(m)+φ(m)(modm)(b≥m)
分析
这道题肯定是用降幂公式啦~(废话)
首先,因为
b
b
b是一个高精数,所以我们要用高模低(两行代码……),求出
b
 
m
o
d
 
φ
(
c
)
b\bmod \varphi(c)
bmodφ(c),至于
φ
(
c
)
\varphi(c)
φ(c),可以用
O
(
n
)
O(\sqrt{n})
O(n)算出来。
似乎没毛病了?交一波,于是——This Happened……
为什么有这种**的东西呢?看一下降幂的那一部分,需要满足
b
≥
m
b\geq m
b≥m,就是有
b
≥
c
b\geq c
b≥c,例如这组数据:2 4 1(LG版),输出应该是21 mod 4=2,但是这样做输出是0,所以如果
b
≤
c
b\leq c
b≤c的话,就可以不用加那个
φ
(
c
)
\varphi(c)
φ(c)了,直接一波上去就好。
参考代码
1: LG版
#include<map>
#include<set>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<ctime>
#include<cmath>
#include<vector>
#include<bitset>
#include<cctype>
#include<string>
#include<sstream>
#include<fstream>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<iomanip>
#include<iostream>
#include<algorithm>
using namespace std;
#define reg register
#define Max(a, b) ( a > b ? a : b )
#define Min(a, b) ( a < b ? a : b )
#define Abs(a) ( a > 0 ? a : -a )
long long a, m, p, b;
char c[20000001];
inline long long phi(long long n) {
long long res = n;
for(reg long long i = 2; i <= sqrt(n); i++) {
if(n % i == 0) {
res = res / i * (i - 1);
while(n % i == 0) n /= i;
}
}
if(n > 1) res = res / n * (n - 1);
return res;
}
inline long long piow(long long a, long long b, long long MOD) {
reg long long ans = 1;
while(b) {
if(b & 1) ans = ans * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
cin >> a >> m >> c;
int len = strlen(c); p = phi(m);
//求c % p
bool flag = 0;
for(reg int i = 0; i < len; i++) {
b = b * 10 + c[i] - '0';
if(b >= p) flag = 1;
b %= p;
}
cout << piow(a, b + flag * p, m) << endl;
}
2:Vjudge版
#include<map>
#include<set>
#include<list>
#include<queue>
#include<deque>
#include<stack>
#include<ctime>
#include<cmath>
#include<vector>
#include<bitset>
#include<cctype>
#include<string>
#include<sstream>
#include<fstream>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<iomanip>
#include<iostream>
#include<algorithm>
using namespace std;
#define reg register
#define Max(a, b) ( a > b ? a : b )
#define Min(a, b) ( a < b ? a : b )
#define Abs(a) ( a > 0 ? a : -a )
long long a, m, p, b;
char c[1000001];
inline long long phi(long long n) {
long long res = n;
for(reg long long i = 2; i <= sqrt(n); i++) {
if(n % i == 0) {
res = res / i * (i - 1);
while(n % i == 0) n /= i;
}
}
if(n > 1) res = res / n * (n - 1);
return res;
}
inline long long piow(long long a, long long b, long long MOD) {
reg long long ans = 1;
while(b) {
if(b & 1) ans = ans * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
while(cin >> a >> c >> m) {
b = 0;//注意清0……
int len = strlen(c); p = phi(m);
//求c % p
bool flag = 0;
for(reg int i = 0; i < len; i++) {
b = b * 10 + c[i] - '0';
if(b >= p) flag = 1;
b %= p;
}
cout << piow(a, b + flag * p, m) << endl;
}
}