ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

问题 F: Fansblog(威尔逊定理+Miller-Rabin素数检测算法)

2019-08-25 18:01:48  阅读:277  来源: 互联网

标签:prime Miller ll number Fansblog 素数 ans he Rabin


题目描述
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 )

输入
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)

输出
For each testcase, output an integer representing the factorial of Q modulo P.

样例输入
复制样例数据
1
1000000007
样例输出
328400734
思路:威尔逊定理+Miller-Rabin素数检测算法
(P为素数)(p-2)! = 1(modp)

q!(q+1)(q+2)----- * p = 1(modp)
那么用1/(q+1)*(q+2)----- * p不就是答案了吗,除法要用逆元

#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long ll;

ll ModMul(ll a,ll b,ll n)//快速积取模 a*b%n
{
    ll ans=0;
    while(b){
        if(b&1)
            ans=(ans+a)%n;
        a=(a+a)%n;
        b>>=1;
    }
    return ans;
}
ll ModExp(ll a,ll b,ll n)//快速幂取模 a^b%n
{
    ll ans=1;
    while(b){
        if(b&1)
            ans=ModMul(ans,a,n);
        a=ModMul(a,a,n);
        b>>=1;
    }
    return ans;
}
bool miller_rabin(ll n)//Miller-Rabin素数检测算法
{
    ll i,j,a,x,y,t,u,s=10;
    if(n==2)
        return true;
    if(n<2||!(n&1))
        return false;
    for(t=0,u=n-1;!(u&1);t++,u>>=1);//n-1=u*2^t
    for(i=0;i<s;i++){
        a=rand()%(n-1)+1;
        x=ModExp(a,u,n);
        for(j=0;j<t;j++){
            y=ModMul(x,x,n);
            if(y==1&&x!=1&&x!=n-1)
                return false;
            x=y;
        }
        if(x!=1)
       	    return false;
    }
    return true;
}
ll inv(ll a,ll mod){//求逆元 
    return ModExp(a,mod-2,mod);
}
int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		ll n,k;
		scanf("%lld",&n);
		for(k = n-1;;k--){
			if(miller_rabin(k)){
				break;
			}
		}
		ll ans = 1;
		for(k++;k <= n-2;k++){
			ans = ModMul(ans,inv(k,n),n);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

标签:prime,Miller,ll,number,Fansblog,素数,ans,he,Rabin
来源: https://blog.csdn.net/weixin_42868863/article/details/100065709

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有