傳送門
給你乙個素數p,讓你求 k!%p, 其中k為比p小的整數裡最大的素數。例如p=5,則k=3。p=11,則k=7。 k! = k*(k-1)*······*2*1;
input第一行包含乙個整數 t(1<=t<=10) 表示測試樣例的個數.
接下來有t行,每行包含乙個素數 p (1e9≤p≤1e14)
output對於每個測試樣例,輸出乙個整數k!%p,代表答案
sample input
1sample output1000000007
328400734//威爾遜定理是(p-1)!modp==p-1因為兩個素數之間的間隔不會超過300,我們從p-1開始乙個個查驗找q。再把(p-1)乘上[q,p-1]的逆元即可。
注意因為數很大,所有涉及乘的地方都要用快速乘。
威爾遜定理:在初等數論中,威爾遜定理給出了判定乙個自然數是否為素數的充分必要條件。
即:當且僅當p為素數時:( p -1 )! ≡ -1 ( mod p ),但是由於階乘是呈**增長的,其結論對於實際操作意義不大。
也就是說(p-1)!mod p == p-1;
//q p
//(q-1)!modp=-1 ==> (p-1)!mod p == p-1;
//q!*(q+1)*(q+2)....(p-1)==(p-1)!
//q!(mod p)==(p-1)!/[(q+1)*(q+2)*(q+3)....(p-1)](mod p)
//q!(mod p)==(p-1)/(q+1)*(q+2)*(q+3)*...*(p-1))(mod p)
因為這裡的數乘法太大了,所以用的快速乘法
#include#includeusing
namespace
std;
typedef
long
long
ll;const
int maxn=1e7+100
; int
prime[maxn];
bool
biaoji[maxn];
int cnt=0
;void
inint()}}
}bool
judge(ll x)
}return1;
} ll mul(ll a,ll b,ll mod)
a=(a+a)%mod;
b>>=1
; }
return ans%mod;
}ll qpow(ll a,ll b,ll mod)
a=mul(a,a,mod)%mod;
b>>=1
; }
return ans%mod;
} //
威爾遜定理是(p-1)!modp==p-1
//q p
//(q-1)!modp=-1 ==> (p-1)!mod p == p-1;
//q!*(q+1)*(q+2)....(p-1)==(p-1)!
//q!(mod p)==(p-1)!/[(q+1)*(q+2)*(q+3)....(p-1)](mod p)
//q!(mod p)==(p-1)/(q+1)*(q+2)*(q+3)*...*(p-1))(mod p)
intmain()
}ll ans=p-1
;
for(ll i=q+1;i<=p-1;i++)
cout
}}
威爾遜定理
而要解這個問題,使用窮舉或暴搜的方法顯然不可取。若要優雅而巧妙地解決這個問題,就需要用到乙個關於素數的著名結論 威爾遜定理 wilson s theorem 十八世紀中葉,一位英國法官約翰 威爾遜爵士,發現了數論中一種極為罕見的關係 取從1到某個質數所有連續正整數的乘積,例如從1乘到11,即11的階...
Fansblog 威爾遜定理
題意 給乙個質數 p 找小於 p 的最大質數 q 並求 q modp p,q epsilon 10 9,10 題解 威爾遜定理 乙個數 n 若是質數,則有 n 1 equiv n 1 mod n 於是可以先令 ans p 1 再對 p 1 到 q 的數對 p 求逆元。p 到 q 之間的距離不會超過3...
威爾遜定理證明
威爾遜定理 當 p 1 1 mod p 時,p 為素數。p p 1 1 即 p 1 equiv p 1 equiv 1 mod p 證明 靜下心看 先假設集合 m 集合 n 任取乙個 a in m a 一定與 p 互質。再假設乙個集合 s a cdot n 對於 forall x in n x 一定...