2019HDU 多校第三场 1006.Fansblog (威尔逊定理+素数判定)

 

在这里插入图片描述

题目大意:给你一个质数P,要你求出P的上一个质数Q,求Q! % P的值。

题解思路:根据威尔逊定理可知如果P是一个素数,那么( P - 1 )! ≡ -1 % P,然后我们就可以将我们要求的式子进行转化,( P - 1 )! = Q! * ( Q+1 )( Q+2 ) * … * ( P-1 ),所以Q! % P = -1/ ( Q+1 )( Q+2 ) * … * ( P-1 ) % P。然后我们需要想的就是怎么找出Q,由于P的范围是1e9->1e14,我们这里就可以用欧拉筛筛出1-1e7的素数,然后将P一个一个往上找,只要找到一个数对1-1e7内的素数取模都不等于0,那么这个就是我们所要找的Q。

注意:由于P的范围到了1e14,所以我们需要在很多地方使用快速乘或是__int128,不然在计算的过程中会爆 longlong。

#include<bits/stdc++.h>

using namespace std;

#define maxn 10000005
#define ll long long
#define lll __int128
typedef pair<int,int> PII;

ll n,m;
int prime[maxn],vis[maxn];
int cnt;

void init(){
    for(ll i=2;i<maxn;i++){
        if(!vis[i])prime[++cnt]=i;
        for(ll j=1;j<=cnt;j++){
            if(i*prime[j]>=maxn)break;
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)break;
        }
    }
}

bool isprime(ll x){
    for(int i=1;i<=cnt;i++)
        if(x%prime[i]==0)return 0;
    return 1;
}

ll poww(ll a,ll b){
    lll ans=1,base=a;
    while(b){
        if(b&1)ans=ans*base%n;
        base=base*base%n;
        b>>=1;
    }
    return (ll)ans;
}

int main()
{
    init();
    int t;cin>>t;
    while(t--){ 
        scanf("%lld",&n);
        m=n-2;
        while(!isprime(m))m-=2;
        lll sum=1;
        for(ll i=m+1;i<=n-2;i++)
            sum=sum*poww(i,n-2)%n;
        printf("%lld\n",(ll)sum);
    }
}

 

posted @ 2019-08-07 15:15  Mmasker  阅读(119)  评论(0编辑  收藏  举报