Fansblog
Time Limit: 2000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 72 Accepted Submission(s): 18
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
Recommend
chendu
思路:首先要知道如果p是一个素数,则(p-1)!%p=p-1,知道这个性质之后,我们就可以暴力向前找p的前一个素数,设为p1。然后求取(p1+1,p-1)这一段区间关于p的逆元,依次与p-1相乘既是答案,需要注意,有可能爆long long 需要用快速乘。
(ps:找p的前一个素数可以用Miller_Rabin素数检测)
AC代码:
#include<bits/stdc++.h>
//#include<vector>
//#include<iostream>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
#define ms(a,b) memset(a, b, sizeof(a))
typedef long long ll;
const int MAXN = 1e5 + 50;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
//const ll MOD = 1e9+7;
template <class T>
inline bool scan_d(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
template <class C>
void deb(const char *name, C val){
cout << name << val <<endl;
}
ll mod_mul(ll a, ll b, ll MOD)
{
ll res = 0;
while (b)
{
if (b & 1)
res = (res + a) % MOD;
a = (a + a) % MOD;
b >>= 1;
}
return res;
}
ll mod_pow(ll a, ll n, ll MOD)
{
ll res = 1;
while (n)
{
if (n & 1)
res = mod_mul(res, a, MOD);
a = mod_mul(a, a, MOD);
n >>= 1;
}
return res;
}
// Miller-Rabin随机算法检测n是否为素数
bool Miller_Rabin(ll n)
{
if (n == 2)
return true;
if (n < 2 || !(n & 1))
return false;
ll m = n - 1, k = 0;
while (!(m & 1))
{
k++;
m >>= 1;
}
for (int i = 1; i <= 50; i++) // 50为Miller-Rabin测试的迭代次数,可以自己调整
{
ll a = rand() % (n - 1) + 1;
ll x = mod_pow(a, m, n);
ll y;
for (int j = 1; j <= k; j++)
{
y = mod_mul(x, x, n);
if (y == 1 && x != 1 && x != n - 1)
return false;
x = y;
}
if (y != 1)
return false;
}
return true;
}
ll t, n;
int main() {
cin >> t;
while(t--){
cin >> n;
ll ed = n - 1;
while(ed){
if(Miller_Rabin(ed))
break;
ed--;
}
ll ans = n - 1;
for(ll i = n-1; i > ed; i--){
ll inv = mod_pow(i, n-2, n);
ans = mod_mul(ans, inv, n);
}
cout << ans << endl;
}
return 0;
}
/*
5 2
01 3 02 03 04
02 1 05
*/

本文探讨了素数在模运算中的特殊性质,特别是在求解特定区间内最大素数的阶乘模运算问题。通过Miller-Rabin算法检测素数,并利用快速乘法优化计算过程。
297

被折叠的 条评论
为什么被折叠?



