当前位置:   article > 正文

hdu6602 Fansblog(威尔逊定理+大整数判断素数+质数密度+逆元)_威尔逊定理 大质数

威尔逊定理 大质数

题目链接

http://acm.hdu.edu.cn/showproblem.php?pid=6608

题目描述

输入输出

样例

Sample Input

1

1000000007

Sample Output

328400734

题意

给定一个大质数P(1e9与1e14之间),找出小于P的最大质数Q,求Q!mod P的值。

思路

先了解一个事实,P与Q之间的差值并不大。因此可以从P开始枚举,同时采用miller_rabin算法判断质数,求出Q。

接下来要求Q!,我们通过威尔逊定理可以求出(P-1)!mod P的值,将其不停除以从Q+1到P-1的值得到Q!mod P的值,使用乘法逆元处理即可。

由于所有的数字都很大,因此两个数相乘可能超过long long的表示范围。

代码

  1. #include <bits/stdc++.h>
  2. #define ll long long
  3. using namespace std;
  4. ll p;
  5. ll ModMul(ll a,ll b,ll n)//快速积取模 a*b%n,处理乘法运算超过long long表示范围的情况
  6. {
  7. ll ans=0;
  8. while(b)
  9. {
  10. if(b&1)
  11. ans=(ans+a)%n;
  12. a=(a+a)%n;
  13. b>>=1;
  14. }
  15. return ans;
  16. }
  17. ll ModExp(ll a,ll b,ll n)//快速幂取模 a^b%n
  18. {
  19. ll ans=1;
  20. while(b)
  21. {
  22. if(b&1)
  23. ans=ModMul(ans,a,n);
  24. a=ModMul(a,a,n);
  25. b>>=1;
  26. }
  27. return ans;
  28. }
  29. bool is_prime(ll n)//Miller-Rabin素数检测算法
  30. {
  31. ll i,j,a,x,y,t,u,s=10;
  32. if(n==2)
  33. return true;
  34. if(n<2||!(n&1))
  35. return false;
  36. for(t=0,u=n-1;!(u&1);t++,u>>=1);//n-1=u*2^t
  37. for(i=0;i<s;i++)
  38. {
  39. a=rand()%(n-1)+1;
  40. x=ModExp(a,u,n);
  41. for(j=0;j<t;j++)
  42. {
  43. y=ModMul(x,x,n);
  44. if(y==1&&x!=1&&x!=n-1)
  45. return false;
  46. x=y;
  47. }
  48. if(x!=1)
  49. return false;
  50. }
  51. return true;
  52. }
  53. ll inv(ll a){
  54. return ModExp(a,p-2,p);
  55. }
  56. int main(){
  57. int t;
  58. cin>>t;
  59. while(t--){
  60. cin>>p;
  61. ll q;
  62. for(q=p-1;q>=2;q--)if(is_prime(q))break;
  63. ll ans=1;
  64. if(q==p-1){
  65. cout<<p-1<<endl;
  66. continue;
  67. }
  68. for(ll i=q+1;i<=p-2;i++){
  69. ans=ModMul(ans,inv(i),p);
  70. }
  71. cout<<ans<<endl;
  72. }
  73. return 0;
  74. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/180234
推荐阅读
相关标签
  

闽ICP备14008679号