题目大意:给你一个质数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 ",(ll)sum); } }