题目链接:HDU-6608 Fansblog
题意:给你一个素数Q 让你找出小于Q的最大的素数P 让你计算P! % Q (P的阶乘模Q)
思路 :根据威尔逊定理 可以求出(Q-1)! %Q等于 Q-1
由于P和Q的差不大,则先从Q依次减2找到P,然后用Q-1依次去乘 [P+1,Q-1]的的%Q的逆元就好了,由于乘法会超long long 所以用快速乘
#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
const int maxn = 1e7+7;
using namespace std;
ll P[maxn],Q;
int T,cnt;
bool vis[maxn];
void getPrime() {
vis[1]=true;
cnt=0;
for(ll i=2;i<maxn;i++) {
if(vis[i])continue;
P[cnt++] = i;
for(ll j=i*i;j<maxn;j+=i) {
vis[j]=true;
}
}
}
ll getP(ll q){
for(ll i=q-2;i>=2;i-=2){
bool flag = false;
for(int j=0;j<cnt;j++) {
if(i%P[j]==0) {
flag=true;
break;
}
}
if(!flag) return i;
}
}
ll mul(ll a,ll b,ll c){
ll ans=0;
while(b){
if(b&1){
ans=(ans+a)%c;
}
b>>=1;
a=(a<<1)%c;
}
return ans%c;
}
ll ksm(ll a,ll b,ll c){
ll ans=1;
while(b) {
if(b&1) ans = mul(ans,a,c);
a = mul(a,a,c);
b>>=1;
}
return ans%c;
}
int main()
{
getPrime();
scanf("%d",&T);
while(T--) {
scanf("%lld",&Q);
ll p = getP(Q);
ll ans = Q-1;
for(ll i=p+1;i<=Q-1;i++) {
ans = mul(ans,ksm(i,Q-2,Q),Q)%Q;
}
printf("%lld\n",ans);
}
return 0;
}