杭电多校 Fansblog

Fansblog

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3170    Accepted Submission(s): 671


 

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

先看着这个:

威尔逊定理

直接暴力找Q,反正两个质数见差不了几个数。1e18的范围内任意两个质数差的值也就三百个左右。

根据威尔逊定理 ,Q!=1/[(Q+1)*(Q+2)+......+(P-2)]  (MOD P);

然后将除法取模变换成乘法取模就好做了

①:ans=(ans+mod)%mod

②:(a*b)%mod = (a%mod)*(b%mod)%mod

③:(a/b)%mod==a*b^(mod-2)%mod

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template <class T>
void read(T &x)
{
    static char ch;
    static bool neg;
    for(ch = neg = 0; ch < '0' || '9' < ch; neg |= ch == '-', ch = getchar());
    for(x = 0; '0' <= ch && ch <= '9'; (x *= 10) += ch - '0', ch = getchar());
    x = neg ? -x : x;
}
int T;
ll n, m;
ll qmul( ll a, ll b )
{
    ll ans = 0;
    while( b )
    {
        if( b & 1 ) ans = ( ans + a ) % m;
        a = ( a + a ) % m;
        b = b >> 1;
    }
    return ans;
}
ll qpow( ll a, ll b )
{
    ll ans = 1;
    while( b )
    {
        if( b & 1 )
            ans = qmul( ans, a );
        a = qmul( a, a );
        b = b >> 1;
    }
    return ans;
}
ll findn(ll m)
{
    for(ll i = m - 1;; i--)
    {
        ll flag = 0;
        for(ll j = 2; j <= sqrt(i); j++)
            if(i % j == 0)
            {
                flag = 1;
                break;
            }
        if(!flag) return i;
    }
}

int main()
{
    read(T);
    while(T--)
    {
        read(m);
        n = findn(m);
        ll ans = 1;
        cout<<n<<m<<endl;
        for(ll i = n + 1; i <= m - 2; i++)
            {
                cout<<qpow( i, m - 2 ) <<endl;
                ans=qmul( ans, qpow( i, m - 2 ) );

            }
        cout << ans << endl;
    }
    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值