赞
踩
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的表示范围。
- #include <bits/stdc++.h>
- #define ll long long
- using namespace std;
- ll p;
-
- ll ModMul(ll a,ll b,ll n)//快速积取模 a*b%n,处理乘法运算超过long long表示范围的情况
- {
- 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 is_prime(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){
- return ModExp(a,p-2,p);
- }
- int main(){
- int t;
- cin>>t;
- while(t--){
- cin>>p;
- ll q;
- for(q=p-1;q>=2;q--)if(is_prime(q))break;
- ll ans=1;
- if(q==p-1){
- cout<<p-1<<endl;
- continue;
- }
- for(ll i=q+1;i<=p-2;i++){
- ans=ModMul(ans,inv(i),p);
- }
- cout<<ans<<endl;
- }
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。