题意:给出质数P(1e9~1e14) ,求出比P小的最大质数Q,输出Q!modP
分析:我是直接从P-1递减判断是否为质数,虽然过了但是很低效,更好的做法是米勒测试,我不会所以就不写了。求出Q之后,就要算Q!modp。直接算显然超时,注意到P为质数,所以想到威尔逊定理 : (p-1)!-1modp当且仅当p为质数时成立,加个模数-1变成P-1。所以倒着算Q!=(P-1)! / [ (p-1) * (p-2) * (p-3)..... * (a+1) ]。中间除法取模要求一下逆元可用费马小定理或ex_gcd。wa了几次后发现题目给的范围可能爆unsignedlonglong,所以这道题的乘法需要使用快速乘,但是听说G++可以int128,没去试,但应该是可行的
代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e7 + 3; bool f(ll n) { for(ll i=2;i*i<=n;i++) if(n%i==0) return false; return true; } ll mul(ll a,ll b,ll mod) { ll ans=0; while(b) { if(b&1) ans=(ans+a)%mod; a=(a<<1)%mod; b>>=1; } return ans; } ll ksm(ll a,ll b,ll mod) { ll ans=1; while(b) { if(b&1) ans=mul(ans,a,mod); a=mul(a,a,mod); b>>=1; } return ans; } int main() { int t; scanf("%d",&t); while(t--) { ll flag,a,b; cin>>b; for(ll i=b-1;i>=0;i--) if(f(i)) { a=i;break; } ll ans=b-1; for(ll i=b-1;i>=a+1;i--) ans=mul(ans,ksm(i,b-2,b),b); printf("%lld\n",ans); } return 0; }