F.Fansblog (Wilson Theorem + Black Technology)

Posted by coffeeguy on Tue, 30 Jul 2019 22:58:19 +0200

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;
} 

 

Topics: less