Title: Give you a prime number P, 1e9<=P<=1e14, ask you the factorial of the first prime number Q (% P) less than P.
Solutions:
- First, the first conclusion is that the distance between two adjacent primes is not too large (Zhenmin will not). For example, the next adjacent primes of 1e9+7 in the example are only 70 bits apart.
- The second theorem: Wilson's theorem: if and only if P is prime: (p-1), -1 (mod-p), it can be deduced (p-2), 1 (mod-p), (Zhenmin will not)
- Then fool around
Pre-skills:
- Inverse Element: When modularizing a fraction, the inverse element of the denominator is needed (see Fermat's small theorem for details).
int Mod(int a,int b){ int c=1; while(b){ if(b%2) c=c*a%mod; b=b/2; a=a*a%mod; } return c; } b The inverse element of Mod(b,mod-2)%mod; x=a*Mod(b,mod-2)%mod;
- Black Science and Technology. Fast Multiplication: Because the data of this problem is very large 1e9<=P<=1e14, it will explode long in the process of multiplication. All multiplication operations with KSC will accomplish each multiplication operation in O(1).
inline ll ksc(ll x,ll y,ll mod)//It is said that if the modulus is too large, it may lead to errors in accuracy. { ll tmp=(x*y-(ll)((long double)x/mod*y+1.0e-8)*mod); return tmp<0 ? tmp+mod : tmp; }
- Black science and technology judging prime number: judging prime number O (sqrt (n), but this black science and technology O (sqrt (n) / 3);
int isPrime(ll n) { //Returning 1 indicates that it is a prime number and 0 is a non-prime number. No input anomaly detection is performed here. float n_sqrt; if(n==2 || n==3) return 1; if(n%6!=1 && n%6!=5) return 0; n_sqrt=floor(sqrt((float)n)); for(ll i=5;i<=n_sqrt;i+=6) { if(n%(i)==0 | n%(i+2)==0) return 0; } return 1; }
Last complete code: the combination of code and technology (hh)
#include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<iostream> #include<stdlib.h> #include<cmath> using namespace std; const int inf=0x3f3f3f3f; const int maxn=1000000; typedef long long ll; int isPrime(ll n) { //Returning 1 indicates that it is a prime number and 0 is a non-prime number. No input anomaly detection is performed here. float n_sqrt; if(n==2 || n==3) return 1; if(n%6!=1 && n%6!=5) return 0; n_sqrt=floor(sqrt((float)n)); for(ll i=5;i<=n_sqrt;i+=6) { if(n%(i)==0 | n%(i+2)==0) return 0; } return 1; } inline ll ksc(ll x,ll y,ll mod)//It is said that if the modulus is too large, it may lead to errors in accuracy. { ll tmp=(x*y-(ll)((long double)x/mod*y+1.0e-8)*mod); return tmp<0 ? tmp+mod : tmp; } ll Mod(ll a,ll b,ll p){ ll c=1; while(b){ if(b%2) c=ksc(c,a,p); b=b/2; a=ksc(a,a,p); } return c; } int main(){ int t; cin>>t; while(t--){ ll p; cin>>p; ll n=p; while(1){ n--; if(isPrime(n)) break; } ll q=n; ll tmp=1; for(ll i=q+1;i<=p-2;i++){ tmp=ksc(tmp,i,p); } ll ans=Mod(tmp,p-2,p)%p; cout<<ans<<endl; } return 0; }