题目大意:给你一个质数P,要你求出P的上一个质数Q,求Q! % P的值。
题解思路:根据威尔逊定理可知如果P是一个素数,那么( P - 1 )! ≡ -1 % P,然后我们就可以将我们要求的式子进行转化,( P - 1 )! = Q! * ( Q+1 )( Q+2 ) * … * ( P-1 ),所以Q! % P = -1/ ( Q+1 )( Q+2 ) * … * ( P-1 ) % P。然后我们需要想的就是怎么找出Q,由于P的范围是1e9->1e14,我们这里就可以用欧拉筛筛出1-1e7的素数,然后将P一个一个往上找,只要找到一个数对1-1e7内的素数取模都不等于0,那么这个就是我们所要找的Q。
注意:由于P的范围到了1e14,所以我们需要在很多地方使用快速乘或是__int128,不然在计算的过程中会爆 longlong。
#include<bits/stdc++.h>
using namespace std;
#define maxn 10000005
#define ll long long
#define lll __int128
typedef pair<int,int> PII;
ll n,m;
int prime[maxn],vis[maxn];
int cnt;
void init(){
for(ll i=2;i<maxn;i++){
if(!vis[i])prime[++cnt]=i;
for(ll j=1;j<=cnt;j++){
if(i*prime[j]>=maxn)break;
vis[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
bool isprime(ll x){
for(int i=1;i<=cnt;i++)
if(x%prime[i]==0)return 0;
return 1;
}
ll poww(ll a,ll b){
lll ans=1,base=a;
while(b){
if(b&1)ans=ans*base%n;
base=base*base%n;
b>>=1;
}
return (ll)ans;
}
int main()
{
init();
int t;cin>>t;
while(t--){
scanf("%lld",&n);
m=n-2;
while(!isprime(m))m-=2;
lll sum=1;
for(ll i=m+1;i<=n-2;i++)
sum=sum*poww(i,n-2)%n;
printf("%lld\n",(ll)sum);
}
}