存一波Miller-Rabin板子 多校第三场Fansblog
Farmer John keeps a website called ‘FansBlog’ .Everyday , there are many people visited this blog.One day, he find the visits has reached P , which is a prime number.He thinks it is a interesting fact.And he remembers that the visits had reached another prime number.He try to find out the largest prime number Q ( Q < P ) ,and get the answer of Q! Module P.But he is too busy to find out the answer. So he ask you for help. ( Q! is the product of all positive integers less than or equal to n: n! = n * (n-1) * (n-2) * (n-3) *… * 3 * 2 * 1 . For example, 4! = 4 * 3 * 2 * 1 = 24 )
直接暴力判断是否是质数也过了。。。
用了威尔逊定理
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; long long prime[10]={2,3,5,7,11,13,17,19,23,29}; long long Quick_Multiply(long long a,long long b,long long c) //快速积 { long long ans=0,res=a; while(b) { if(b&1) ans=(ans+res)%c; res=(res+res)%c; b>>=1; } return (long long)ans; } long long Quick_Power(long long a,long long b,long long c) { long long ans=1,res=a; while(b) { if(b&1) ans=Quick_Multiply(ans,res,c); res=Quick_Multiply(res,res,c); b>>=1; } return ans; } bool Miller_Rabin(long long x) //判断素数 { long long i,j,k; long long 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) //随便选一个素数进行测试 { long long a=prime[i]; long long b=Quick_Power(a,t,x); //先算出a^t for(j=1;j<=s;++j) //然后进行s次平方 { k=Quick_Multiply(b,b,x); //求b的平方 if(k==1&&b!=1&&b!=x-1) //用二次探测判断 return false; b=k; } if(b!=1) return false; //用费马小定律判断 } return true; //如果进行多次测试都是对的,那么x就很有可能是素数 } long long ex_gcd(long long a,long long b,long long &x,long long &y) { if(b==0){x = 1;y = 0;return a;} long long ans = ex_gcd(b,a%b,x,y); long long temp = x; x = y; y = temp - a/b*y; return ans; } long long inv(long long a,long long b) { long long x,y; long long ans = ex_gcd(a,b,x,y); if(ans!=1)return -1; if(x<0)x = (x%b + b)%b; return x; } __int128 aa, ab, am; long long sb(long long a, long long b, long long m) { aa = a, ab = b, am = m; return (long long)(aa * ab % am); } int main() { long long p; long long T; scanf("%lld",&T); while(T--) { long long ans=1; scanf("%lld",&p); for(long long i=p-1;;i--) { if(Miller_Rabin(i))break; ans=sb(ans,inv(i,p),p); } printf("%lld\n",p-ans); } return 0; }