• HDU6608-Fansblog(Miller_Rabbin素数判定,威尔逊定理应用,乘法逆元)


    Problem Description
    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 )
     
    Input
    First line contains an number T(1<=T<=10) indicating the number of testcases.
    Then T line follows, each contains a positive prime number P (1e9≤p≤1e14)
     
    Output
    For each testcase, output an integer representing the factorial of Q modulo P.
     
    Sample Input
    1 1000000007
     
    Sample Output
    328400734
     
    Source

    题意:

    找出Q,Q为比P小的数中的最大素数,求Q!

    题解:

    用Miller_Rabbin素数检测快速找出Q,用威尔逊定理 ,求出(P-1)! 

    根据乘法逆元,用除的模求出Q!

    Code:

      1 #include <iostream>
      2 #include <algorithm>
      3 #include <time.h>
      4 using namespace std;
      5 /**
      6 Miller_Rabin 算法进行素数测试
      7 快速判断一个<2^63的数是不是素数,主要是根据费马小定理
      8 */
      9 #define ll __int128
     10 const int S=8; ///随机化算法判定次数
     11 ll MOD;
     12 ///计算ret=(a*b)%c  a,b,c<2^63
     13 ll mult_mod(ll a,ll b,ll c)
     14 {
     15     a%=c;
     16     b%=c;
     17     ll ret=0;
     18     ll temp=a;
     19     while(b)
     20     {
     21         if(b&1)
     22         {
     23             ret+=temp;
     24             if(ret>c)
     25                 ret-=c;//直接取模慢很多
     26         }
     27         temp<<=1;
     28         if(temp>c)
     29             temp-=c;
     30         b>>=1;
     31     }
     32     return ret;
     33 }
     34 
     35 ///计算ret=(a^n)%mod
     36 ll pow_mod(ll a,ll n,ll mod)
     37 {
     38     ll ret=1;
     39     ll temp=a%mod;
     40     while(n)
     41     {
     42         if(n&1)
     43             ret=mult_mod(ret,temp,mod);
     44         temp=mult_mod(temp,temp,mod);
     45         n>>=1;
     46     }
     47     return ret;
     48 }
     49 
     50 ///通过费马小定理 a^(n-1)=1(mod n)来判断n是否为素数
     51 ///中间使用了二次判断,令n-1=x*2^t
     52 ///是合数返回true,不一定是合数返回false
     53 bool check(ll a,ll n,ll x,ll t)
     54 {
     55     ll ret=pow_mod(a,x,n);
     56     ll last=ret;//记录上一次的x
     57     for(int i=1;i<=t;i++)
     58     {
     59         ret=mult_mod(ret,ret,n);
     60         if(ret==1&&last!=1&&last!=n-1)
     61             return true;//二次判断为是合数
     62         last=ret;
     63     }
     64     if(ret!=1)
     65         return true;//是合数,费马小定理
     66     return false;
     67 }
     68 
     69 
     70 ///Miller_Rabbin算法
     71 ///是素数返回true(可能是伪素数),否则返回false
     72 bool Miller_Rabbin(ll n)
     73 {
     74     if(n<2) return false;
     75     if(n==2) return true;
     76     if((n&1)==0) return false;//偶数
     77     ll x=n-1;
     78     ll t=0;
     79     while((x&1)==0)
     80     {
     81         x>>=1;
     82         t++;
     83     }
     84     srand(time(NULL));
     85     for(int i=0;i<S;i++)
     86     {
     87         ll a=rand()%(n-1)+1; // 生成随机数 0<a<=n-1  去试试
     88         if(check(a,n,x,t))
     89             return false;
     90     }
     91     return true;
     92 }
     93 
     94 //------------------------------------------------------------------------求素数
     95 inline ll pow(const ll n, const ll k) {
     96     ll ans = 1;
     97     for (ll num=n,t=k;t;num=num*num%MOD,t>>=1) if(t&1) ans=ans*num%MOD;
     98     return ans%MOD;
     99 }
    100 
    101 inline ll inv(const ll num) {
    102     return pow(num, MOD - 2);
    103 }
    104 //求乘法逆元
    105 
    106 int main(){
    107     ll ans;
    108     int T;
    109     long long a;
    110     cin>>T;
    111     while(T--){
    112         cin>>a;
    113         MOD=a;
    114         a--;
    115         while(!Miller_Rabbin(a)) a--;
    116         ans=MOD-1;
    117         for(ll i=a+1;i<=MOD-1;i++){
    118             ans=(ans%MOD*inv(i)%MOD)%MOD;
    119         }
    120         a=ans;
    121         cout<<a<<'
    ';
    122     }
    123 }
  • 相关阅读:
    SAP BDC批量导入数据(转)
    如何快速从BSEG读取数据(转)
    刷新ALV定位到当前记录行
    一些常用的系统变量(SYST)
    javascript实例
    selenium webDriver属性
    获取豆瓣电影数据
    新浪微博超话题签到demo
    java读取XML文件的四种方法总结(必看篇)
    StringReader分析
  • 原文地址:https://www.cnblogs.com/Never-Land/p/11269393.html
Copyright © 2020-2023  润新知