hdu 2837 Calculation 指数循环节套路题
Calculation
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2272 Accepted Submission(s): 536
Problem Description
Assume that f(0) = 1 and 0^0=1. f(n) = (n%10)^f(n/10) for all n bigger than zero. Please calculate f(n)%m. (2 ≤ n , m ≤ 10^9, x^y means the y th power of x).
Input
The first line contains a single positive integer T. which is the number of test cases. T lines follows.Each case consists of one line containing two positive integers n and m.
Output
One integer indicating the value of f(n)%m.
Sample Input
2
24 20
25 20
Sample Output
16
5
题意:求解$f(n) = {(n\%10)}^{f(n/10)}\%m $,其中$(2 <= n, m <= 10^9)$;
思路:一看到指数模除,并且没有说明是否互素,直接上指数循环节,化简指数==套路...
注:
1. 使用指数循环节都是递归形式,所以欧拉函数也需要是递归形式;
2. 在指数循环节中的快速幂时,需要在ans >= mod时,模完之后还要加上mod;
1 #include <iostream> 2 #include<cstdio> 3 using namespace std; 4 #define ll long long 5 ll phi(ll c) 6 { 7 ll ans = c; 8 for(int i = 2; i*i <= c; i++) { 9 if(c%i == 0){ 10 ans -= ans/i; 11 while(c%i == 0) c /= i; 12 } 13 } 14 if(c > 1) ans -= ans/c; 15 return ans; 16 } 17 ll quick_mod(ll a, ll b, ll mod) 18 { 19 if(a >= mod) a = a%mod + mod; // 并不是直接%mod 20 ll ans = 1; 21 while(b){ 22 if(b&1){ 23 ans = ans*a; 24 if(ans >= mod) ans = ans%mod + mod; //** 25 } 26 a *= a; 27 if(a >= mod) a = a%mod + mod; //** 28 b >>= 1; 29 } 30 return ans; 31 } 32 ll solve(ll n, ll m) 33 { 34 ll p = phi(m); 35 if(n == 0) return 1; 36 ll index = solve(n/10, p); 37 38 return quick_mod(n%10, index, m); 39 } 40 int main() 41 { 42 ll n, m, T; 43 cin >> T; 44 while(T--){ 45 scanf("%I64d%I64d", &n, &m); 46 printf("%I64d\n", solve(n,m)%m); 47 } 48 return 0; 49 }