(1) Several basic definitions
/*Although we don't need to know how to prove Euler's function, we still need to know what it is*/
1) Euler function:
Definition: For a positive integer n, the number of positive integers less than n and coprime to n is denoted as φ(n), and φ(1) is defined as a 1
property: Obviously, for prime numbers p, q, satisfy φ( n) =(p-1)(q-1)=pq+1-pq/p-pq/q
property: Obviously, for prime numbers p, q, satisfy φ( n) =(p-1)(q-1)=pq+1-pq/p-pq/q
Here's how to find the Euler function:
ll euler(ll n){ int cnt=n,nownum=n; for(ll i = 2 ; i*i <= nownum ; i ++) if(nownum % i == 0){ cnt -= cnt/i; //mark 1 while(nownum % i == 0) nownum /= i; } if(nownum > 1) cnt -= cnt/nownum; return cnt; }
The place marked 1 actually involves a mathematical knowledge, although I do not understand the specifics (after all, it will be used), but roughly, if a number n has a factor 3 and a factor 5, After crossing out all the numbers from 1 to n that are multiples of 3, in the remaining (nn/3) numbers, the number of times the number that is a multiple of 5 appears is (nn/3)/5. For example: n=20, remove the numbers that are multiples of 5, leaving 1, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 18, 19, of which 2 There are still 8 numbers of multiples, and (20-20/5)/2=8, so there is no problem in writing the mark 1 like this, please prove it. . . . . I won't
2) Euler's theorem:
Definition: a^(φ(n)+1) mod n = a , a and n are relatively prime positive integers
/* The above is actually useless. The thing that completes the task of reducing power in general problem solving is the following formula*/
Generalization: a^b ≡ a^(b%φ(n)+φ(n)) mod n , when b<=φ(m), you can directly use the fast power
Therefore, from this formula, we find that when b is very large, it can be reduced to b%φ(n)+φ(n), thus achieving the effect of power reduction.
(2) Example 1:
Click to open the link
The meaning of a sentence is: find f(n) = 2^f(n-1) mod p, n defaults to 10^9, f(1) = 1, p is given by the data input
AC code:
#include<iostream> using namespace std; typedef long long ll; ll euler(ll n){ ll cnt = n, nownum = n; for(ll i = 2; i * i <= nownum; i++){ if(nownum % i == 0){ cnt -= (cnt / i); while(nownum % i == 0) nownum /= i; } } if(nownum > 1) cnt -= (cnt/nownum); // cout << "euler:" << cnt << endl; return cnt; } ll fast_mod(ll x, ll y, ll p){ // x^y % p ll ans = 1, tag = x; while(y > 0){ if(y & 1) years = (years * tag) %p; day = (day * day) % p; y >>= 1; } // cout << "fast_mod:" << ans << endl; return ans; } ll func(ll n, ll p){ //f(n-1) % &p + &p // printf("func(%lld)\n",&n); if(p == 1) return 0; if(n == 1) return 1; if(n == 2) return 2 % p; if(n == 3) return 4 % p; if(n == 4) return 16 % p; else{ ll e = euler(p); ll a = func(n-1, e) + e; ll fn = fast_mod(2, a, p); return fn; } } int main(){ // cout << euler(1) << endl; // cout << euler(2) << endl; // cout << euler(3) << endl; // cout << fast_mod(2,3,1000) << endl; // cout << fast_mod(3,2,3) << endl; // cout << fast_mod(3,2,1000) << endl; int T, p; cin >> T; while(T--){ cin >> p; cout << func(1000000000, p) << endl; } return 0; }
f(n) = 2^f(n-1) mod p;
即 f (n) = 2 ^ (f (n-1) mod φ (p) + φ (p)) mod p;
So relying on the recursive function to achieve, originally thought that the end point of the recursion is n==1, but later found out when debugging, in fact, the recursion is generally terminated when p==1, because φ(φ(φ(...φ(p )))) This drop must be faster than the decrease of n by 1 each time. . . . And I originally added this sentence to prevent p=1 from being given when the question is input, so it doesn't need to be forgotten. Any number modulo 1 is 0, but the result is because this is right, so don't forget to discuss p Case.
(2) Example 2: The link of csu2021 is gone. It can be found. In fact, it is basically the same as the above topic, but here is f(n)=n^f(n-1) mod p
AC code:
ll func(ll n,ll m){ if(m == 1) return 0; if(n == 1) return 1; else if(n == 2) return 2%m; else if(n == 3) return 9%m; else if(n == 4) return fast_mod(4,9,m); else{ ll e=euler(m); ll z=func(n-1,e); ll ans=fast_mod(n,e+z,m); return ans; } }