FansBlog - 2019 Multi-University Training Contest 1
题目
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)
样例输入
1
1000000007
输出
For each testcase, output an integer representing the factorial of Q modulo P.
样例输出
328400734
题意
有一个质数P (1e9≤p≤1e14),要求找到比P小但是和P的差最小的质数Q,求Q! mod P.
题解
质数分布:任意2000个自然数以内一定存在质数。
因此对于[P-1,P-2001]的区间的每一个数,判断它是否是质数,一旦找到质数则为Q
然后用Wilson定理计算答案
注意计算过程的数据可能很大,需要__int128
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll MOD;
ll power(ll x, unsigned long long y, ll p) {
ll res = 1LL;
x = x % p;
while (y > 0) {
if (y & 1LL)
res = (res * x) % p;
y = y >> 1LL;
x = (x * x) % p;
}
return res;
}
ll prime[7] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022};
ll qm(ll a, ll b, ll c) {
long long ans = 0, res = a;
while (b) {
if (b & 1)
ans = (ans + res) % c;
res = (res + res) % c;
b >>= 1;
}
return (ll)ans;
}
ll mul(ll a, ll b) { return (ll)(__int128(a) * b % MOD); }
ll qp(ll a, ll b, ll c) {
ll ans = 1, res = a;
while (b) {
if (b & 1)
ans = qm(ans, res, c);
res = qm(res, res, c);
b >>= 1;
}
return ans;
}
__int128 qp2(__int128 a, __int128 b, __int128 c) {
__int128 ans = 1, res = a;
while (b) {
if (b & 1)
ans = qm(ans, res, c);
res = qm(res, res, c);
b >>= 1;
}
return ans;
}
bool Miller_Rabin(ll x) {
ll i, j, k;
ll s = 0, t = x - 1;
if (x == 2)
return true;
if (x < 2 || !(x & 1))
return false;
while (!(t & 1)) {
s++;
t >>= 1;
}
for (i = 0; i < 6 && prime[i] < x; ++i) {
ll a = prime[i];
ll b = qp(a, t, x);
for (j = 1; j <= s; ++j) {
k = qm(b, b, x);
if (k == 1 && b != 1 && b != x - 1)
return false;
b = k;
}
if (b != 1)
return false;
}
return true;
}
__int128 modInverse(__int128 a, __int128 p) { return qp(a, p - 2ll, p); }
ll modFact(ll n, ll p) {
if (p <= n)
return 0;
__int128 res = (p - 1ll);
for (__int128 i = n + 1ll; i < p; i++) {
res = ((res % p) * (modInverse(i, p) % p)) % p;
}
return (ll)res;
}
int main() {
ll t;
scanf("%lld", &t);
while (t-- > 0) {
scanf("%lld", &MOD);
ll i;
for (i = MOD - 1; i > MOD - 2001; i--) {
if (Miller_Rabin(i))
break;
}
printf("%lld\n", modFact(i, MOD));
}
return 0;
}