前言:
这题我不会,我是真的不会,数论一窍不通,我只负责记住结论
快速测素数法:
我把代码改成我喜欢用的模式
quick_prime()由三部分组成
一开始定义要测的素数
ll prime[10]= {2,3,5,7,11,13,17,19,23,29};
第一部分
ll quick_mul(ll a,ll b,ll mod) //快速积
{
long long ans=0,res=a;
while(b)
{
if(b&1)
ans=(ans+res)%mod;
res=(res+res)%mod;
b>>=1;
}
return (ll)ans;
}
第二部分
ll quick_mi(ll a,ll b,ll mod) //快速幂
{
ll ans=1,res=a;
while(b)
{
if(b&1)
ans=quick_mul(ans,res,mod);
res=quick_mul(res,res,mod);
b>>=1;
}
return ans;
}
第三部分
bool quick_prime(ll x) //快速判断素数
{
ll i,j,k;
ll s=0,t=x-1;
if(x==2) return true; //2是素数
if(x<2||!(x&1)) return false; //如果x是偶数或者是0,1,那它不是素数
while(!(t&1)) //将x分解成(2^s)*t的样子
{
s++;
t>>=1;
}
for(i=0; i<10&&prime[i]<x; ++i) //随便选一个素数进行测试
{
ll a=prime[i];
ll b=quick_mi(a,t,x); //先算出a^t
for(j=1; j<=s; ++j) //然后进行s次平方
{
k=quick_mul(b,b,x); //求b的平方
if(k==1&&b!=1&&b!=x-1) //用二次探测判断
return false;
b=k;
}
if(b!=1) return false; //用费马小定律判断
}
return true; //如果进行多次测试都是对的,那么x就很有可能是素数
}
威尔逊定理:
p 为质数⟺(p−1)!≡−1(mod p)
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
ll prime[10]= {2,3,5,7,11,13,17,19,23,29};
ll quick_mul(ll a,ll b,ll mod) //快速积(和快速幂差不多)
{
long long ans=0,res=a;
while(b)
{
if(b&1)
ans=(ans+res)%mod;
res=(res+res)%mod;
b>>=1;
}
return (ll)ans;
}
ll quick_mi(ll a,ll b,ll mod) //快速幂,这里就不赘述了
{
ll ans=1,res=a;
while(b)
{
if(b&1)
ans=quick_mul(ans,res,mod);
res=quick_mul(res,res,mod);
b>>=1;
}
return ans;
}
bool quick_prime(ll x) //判断素数
{
ll i,j,k;
ll s=0,t=x-1;
if(x==2) return true; //2是素数
if(x<2||!(x&1)) return false; //如果x是偶数或者是0,1,那它不是素数
while(!(t&1)) //将x分解成(2^s)*t的样子
{
s++;
t>>=1;
}
for(i=0; i<10&&prime[i]<x; ++i) //随便选一个素数进行测试
{
ll a=prime[i];
ll b=quick_mi(a,t,x); //先算出a^t
for(j=1; j<=s; ++j) //然后进行s次平方
{
k=quick_mul(b,b,x); //求b的平方
if(k==1&&b!=1&&b!=x-1) //用二次探测判断
return false;
b=k;
}
if(b!=1) return false; //用费马小定律判断
}
return true; //如果进行多次测试都是对的,那么x就很有可能是素数
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll p;
scanf("%lld",&p);
ll Q=p-1;
while(!quick_prime(Q))//快速求得素数Q
{
Q--;
}
//printf("%lld\n", Q);
ll ans=p-1;
for (ll i = p - 1; i > Q; --i)
ans = quick_mul(ans, quick_mi(i, p - 2, p), p);
printf("%lld\n",ans);
}
}