- 题意
- 给一个质数p(1e9<=p<=1e14)
- 求比p小的最大质数q
- 求q! mod p
- 题解
- 1e14附近的素数密度很大(理论上logn,实际上要更小一些)
- 直接选择暴力筛或者先筛出1e7的质数再以此暴力应该都行
- 由威尔逊顶定理:(p-1)!mod p =1
- 所以q! mod p = 1/((prime(n)+1)*(prime(n)+2)*…*(prime(n+1)-2)) mod prime(n+1) (n>1)
- 求个逆元即可
- 代码
-
#include<algorithm> #include <iostream> #include <fstream> #include <cstdlib> #include <cstring> #include <cassert> #include <cstdio> #include <vector> #include <string> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> using namespace std; #define P(a,b,c) make_pair(a,make_pair(b,c)) #define rep(i,a,n) for (int i=a;i<=n;i++) #define per(i,a,n) for (int i=n;i>=a;i--) #define CLR(vis) memset(vis,0,sizeof(vis)) #define MST(vis,pos) memset(vis,pos,sizeof(vis)) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef pair<int,pair<int,int> >pii; typedef long long ll; typedef unsigned long long ull; const ll mod = 1000000007; const int INF = 0x3f3f3f3f; ll gcd(ll a, ll b) { return b ? gcd(b, a%b) : a; } template<class T>inline void gmax(T &A, T B) { (A<B)&&(A=B);//if(B>A)A=B; } template<class T>inline void gmin(T &A, T B) { (A>B)&&(A=B);//if(B<A)A=B; } template <class T> inline bool scan_d(T &ret) { char c; int sgn; if(c=getchar(),c==EOF) return 0; //EOF while(c!='-'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1; } inline void outt(int x) { if(x>9) outt(x/10); putchar(x%10+'0'); } bool is_prime(ll x){ for(ll i =2;i*i<=x;i++){ if(x%i==0){ return false; } } return true; } ll p,q; ll q_plus(ll a,ll b){ ll sum=0; while(b){ if(b&1)sum=(sum+a)%p; b/=2; a = (a+a)%p; } return sum; } ll qow(ll a,ll b){ ll sum=1; while(b){ if(b&1)sum=q_plus(sum,a)%p; b/=2; a = q_plus(a,a)%p; } return sum; } int main(){ int t; scanf("%d",&t); while(t--){ //scanf("%I64d", &p); cin>>p; for(ll i=p-1;i>=2;i--){ if(is_prime(i)){ q=i; break; } } ll sum=1; for(ll i=q+1;i<=p-2;i++){ sum = q_plus(sum,i)%p; } //printf("%I64d\n", qow(sum,p-2)%p); cout<< qow(sum,p-2)%p<<endl; } return 0; }
-
叶神版本:
#include <stdio.h> #include <string.h> #include <iostream> #include <string> #include <algorithm> #include <vector> #include <map> using namespace std; typedef long long LL; typedef unsigned long long ULL; const int maxn = 1e7+7; const int inf = 0x3f3f3f3f; int prime[maxn+1]; void init() { for(LL i=2;i<=maxn;i++) { if(!prime[i]) prime[++prime[0]]=i; for(LL j=1;j<=prime[0] && prime[j]<=maxn/i;j++) { prime[i*prime[j]]=1; if(i%prime[j]==0) break; } } } bool check(LL x) { for(int i=1;i<=prime[0] && prime[i]<x;i++) if(x%prime[i]==0) return false; return true; } LL mulmod(LL a,LL b,LL c) { LL res=0; while(b) { if(b&1) res=(res+a)%c; a=(a+a)%c; b=b>>1; } return res; } LL qsm(LL a,LL b,LL c) { LL res=1; while(b) { if(b&1) res=mulmod(res,a,c)%c; a=mulmod(a,a,c)%c; b=b>>1; } return res; } int T; LL P,Q; int main() { init(); /* for(int i=2;i<=100;i++) { LL ans=1; for(int j=1;j<=prime[i-1];j++) ans=ans*j%prime[i]; printf("P:%d Q:%d ans:%lld\n",prime[i],prime[i-1],ans); } */ scanf("%d",&T); while(T--) { scanf("%lld",&P); for(LL i=P-1;;i--) { if(check(i)) { Q=i; //printf("Q=%lld\n",Q); LL t=P-Q-1; LL ans=1; for(LL k=2;k<=t;k++) { //printf("%lld %lld\n",k,qsm(k,P-2,P)); ans=mulmod(ans,qsm(k,P-2,P),P)%P; } printf("%lld\n",ans); break; } } } return 0; }