最主要的步骤是用 1式子和2式子推 3式子。(难点,看了很多博客最后的时候那个式子看不懂)
- 当n, m互质时即gcd(n, m) == 1,存在phi(n * m) = phi(m) * phi(n)
- 当m为素数且n%m == 0时,存在phi(n*m) = phi(n) * m
- 记 为S(n, m),存在S(n,m) = S(n/p, m) * (p – 1) + S(n, m/p) (其中p为素数)
#include<bits/stdc++.h> #define LL long long using namespace std; const int MAXN = 1e7 + 9; const int mod = 1e9 + 7; bool check[MAXN]; int phi[MAXN], prime[MAXN], tot; LL sum[MAXN],now[MAXN]; LL myPow(LL a, int p, LL mod){ LL ret = 1; while(p){ if(p & 1) ret = ret * a % mod; a = a * a % mod; p >>= 1; } return ret; } void phi_and_prime_table(int N) { memset(check,false,sizeof(check)); phi[1] = 1; tot = 0; for(int i = 2; i <= N; i++) { if( !check[i] ) { prime[tot++] = i; phi[i] = i - 1; } for(int j = 0; j < tot; j++) { if(i * prime[j] > N) break; check[i * prime[j]] = true; if( i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j]; break; } else { phi[i * prime[j]] = phi[i] * (prime[j] - 1); } } } for(int i = 1; i <= N; i ++){ sum[i] = (sum[i - 1] + phi[i]) % mod; } } LL S(int n, int m){ if( n == 1 ) return sum[m]; if( m == 0 ) return 0; for(int i = 0; i < tot && prime[i] <= n; i ++){ if( n % prime[i] == 0 ) { int p = prime[i]; return (( 1LL * (p - 1) * S(n/p, m))%mod + S(n, m/p) % mod ) % mod; } } } LL A(int k,int p){ if(k == 1) return 1; if(p == 1) return 0; return myPow(k, phi[p] + A(k, phi[p]), p); } int main() { phi_and_prime_table(10000000); int n,m,p; while(~scanf("%d%d%d",&n,&m,&p)){ int k = S(n,m); printf("%lld ",A(k, p)); } return 0; }