题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=6608
题 目 说 给 你 一 个 1 e 9 − 1 e 14 的 素 数 p , 让 你 找 到 比 p 小 的 最 大 素 数 q , 求 q ! m o d    p 的 值 题目说给你一个1e9-1e14的素数p,让你找到比p小的最大素数q,求q! \mod p的值 题目说给你一个1e9−1e14的素数p,让你找到比p小的最大素数q,求q!modp的值
我 们 知 道 相 邻 两 个 素 数 之 间 的 距 离 不 会 很 大 , 一 般 小 于 l o g n , 所 以 我 们 可 以 从 p − 1 开 始 枚 举 q , 用 米 勒 罗 宾 判 定 是 否 为 素 数 即 可 找 到 q , 根 据 威 尔 逊 定 理 ( p − 1 ) ! ≡ − 1 ( m o d p ) , 用 − 1 乘 上 p − 1 , p − 2 , p − 3 … … q + 1 的 逆 元 即 可 我们知道相邻两个素数之间的距离不会很大,一般小于logn,所以我们可以从p-1开始枚举q,用米勒罗宾判定是否为素数即可找到q,根据威尔逊定理 (p-1)!\equiv-1(mod\ p),用-1乘上p-1,p-2,p-3……q+1的逆元即可 我们知道相邻两个素数之间的距离不会很大,一般小于logn,所以我们可以从p−1开始枚举q,用米勒罗宾判定是否为素数即可找到q,根据威尔逊定理(p−1)!≡−1(mod p),用−1乘上p−1,p−2,p−3……q+1的逆元即可
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn = 2e5 + 500;
int t;
ll p,q,ans;
ll qmul(ll a, ll b, ll mod)
{
ll res = 0;
while(b)
{
if (b & 1)
res = (res + a) % mod;
a = (a << 1) % mod;
b >>= 1;
}
return res;
}
ll qpow(ll x, ll n, ll mod)
{
ll res = 1;
while(n)
{
if (n & 1)
res = qmul(res, x, mod);
x = qmul(x, x, mod);
n >>= 1;
}
return res;
}
bool Miller_Rabin(ll n){
if(n==2)return true;
if(n<2||!(n&1))return false;
int cishu=2,ji=0;
ll m=n-1;
while(!(m&1)){
ji++;
m>>=1;
}
srand(100);
while(cishu--){
ll a=rand()%(n-1)+1;
ll x=qpow(a,m,n),tmp=0;
for(int i=0;i<ji;i++){
tmp=qmul(x,x,n);
if(tmp==1&&x!=1&&x!=n-1)return false;
x=tmp;
}
if(tmp!=1)return false;
}
return true;
}
int main()
{
scanf("%d", &t);
while(t--)
{
scanf("%lld", &p);
q = p - 1;
while(!Miller_Rabin(q))
--q;
printf("%lld\n", q);
ans = p - 1;
for (ll i = p - 1; i > q; --i)
ans = qmul(ans, qpow(i, p - 2, p), p);
printf("%lld\n", ans);
}
return 0;
}