Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2801 Accepted Submission(s): 1158
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
Source
2019 Multi-University Training Contest 3
问题链接:HDU6608 Fansblog
问题简述:给定一个109−1014内的质数p,求小于p的最大质数的阶乘取模p。
问题分析:
这个问题的解决需要用到Miller_Rabin素性测试算法和威尔逊定理,这里不做解释。
程序说明:
快速模幂计算过程中需要做乘法,有可能会产生溢出,所以需要用一个函数来实现。还有一种方法是使用128位整数计算。
参考链接:(略)
题记:(略)
AC的C++语言程序如下:
/* HDU6608 Fansblog */
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
const int TIME = 5;
ULL gcd(ULL a, ULL b) {
return b == 0 ? a : gcd(b, a % b);
}
// 快速乘积,计算a*b
ULL mulmod(ULL a, ULL b, ULL m)
{
ULL ret = 0;
while(b) {
if(b & 1) {ret += a; ret %= m;}
a = (a << 1) % m;
b >>= 1;
}
return ret;
}
// 快速模幂计算
ULL powmod(ULL a, ULL b, ULL mod)
{
ULL ret = 1;
while(b) {
if(b & 1) ret = mulmod(ret, a, mod);
a = mulmod(a, a, mod);
b >>= 1;
}
return ret;
}
ULL random(ULL n)
{
return (ULL)((double) rand() / RAND_MAX * n + 0.5);
}
bool check(ULL a, ULL n)
{
ULL m = n - 1;
int t = 0;
while((m & 1) == 0) {t++; m >>= 1;}
ULL x = powmod(a, m, n);
if(x == 1 || x == n - 1)
return false;
while(t--) {
x = mulmod(x, x, n);
if(x == n - 1)
return false;
}
return true;
}
bool Miller_Rabin(ULL n)
{
if(n < 2) return false;
if(n == 2) return true;
if((n & 1) == 0) return false;
ULL x = n - 1;
ULL t = 0;
while((x&1) == 0) {
x >>= 1;
t++;
}
for(int i = 0; i <= TIME; i++)
{
ULL a = random(n - 2) + 1;
if(check(a, n)) return false;
}
return true;
}
int main()
{
int t;
ULL n;
scanf("%d", &t);
while(t--) {
scanf("%llu", &n);
ULL p = n - 1;
while(!Miller_Rabin(p)) p--;
ULL ans = 1;
for(ULL i = p + 1; i < n - 1; i++)
ans = mulmod(ans, powmod(i, n - 2, n), n);
printf("%llu\n", ans);
}
return 0;
}
AC的C++语言程序如下:
/* HDU6608 Fansblog */
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ULL;
ULL gcd(ULL a,ULL b) {
return b == 0 ? a : gcd(b, a % b);
}
// 快速乘积,计算a*b
ULL mulmod(ULL a, ULL b, ULL m)
{
ULL ret = 0;
while(b) {
if(b & 1) {ret += a; ret %= m;}
a = (a << 1) % m;
b >>= 1;
}
return ret;
}
// 快速模幂计算
ULL powmod(ULL a, ULL b, ULL mod)
{
ULL ret = 1;
while(b) {
if(b & 1) ret = mulmod(ret, a, mod);
a = mulmod(a, a, mod);
b >>= 1;
}
return ret;
}
bool check(ULL a, ULL n)
{
ULL m = n - 1;
int t = 0;
while((m & 1) == 0) {t++; m >>= 1;}
ULL x = powmod(a, m, n);
if(x == 1 || x == n - 1)
return false;
while(t--) {
x = mulmod(x, x, n);
if(x == n - 1)
return false;
}
return true;
}
bool Miller_Rabin(ULL n)
{
if(n == 2) return true;
if(n == 1 || !(n & 1)) return false;
const ULL prime[12] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
for(int i = 0; i < 12; i++) {
if (prime[i] >= n) break;
if(check(prime[i], n)) return false;
}
return true;
}
int main()
{
int t;
ULL n;
scanf("%d", &t);
while(t--) {
scanf("%llu", &n);
ULL p = n - 1;
while(!Miller_Rabin(p)) p--;
ULL ans = 1;
for(ULL i = p + 1; i < n - 1; i++)
ans = mulmod(ans, powmod(i, n - 2, n), n);
printf("%llu\n", ans);
}
return 0;
}