結果
| 問題 |
No.109 N! mod M
|
| ユーザー |
codershifth
|
| 提出日時 | 2015-10-06 01:23:41 |
| 言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
| 結果 |
AC
|
| 実行時間 | 111 ms / 5,000 ms |
| コード長 | 3,354 bytes |
| コンパイル時間 | 1,334 ms |
| コンパイル使用メモリ | 161,596 KB |
| 実行使用メモリ | 6,944 KB |
| 最終ジャッジ日時 | 2024-06-22 04:52:48 |
| 合計ジャッジ時間 | 2,027 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 9 |
ソースコード
#include <bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
#define FOR(i,a,b) for(int (i)=(a);i<(b);i++)
#define REP(i,n) FOR(i,0,n)
#define RANGE(vec) (vec).begin(),(vec).end()
using namespace std;
std::vector<int> primeFactor(int n) {
std::vector<int> res;
for (int i = 2; i*i <= n; ++i)
{
if (n%i == 0)
{
res.push_back(i);
while (n%i==0)
n /= i;
}
}
if (n!= 1)
res.push_back(n);
return std::move(res);
}
template<typename T>
T extgcd(T a, T b, T &x, T &y)
{
T d = a;
if (b != 0)
{
d = extgcd(b, a%b, y, x);
y -= (a/b)*x;
}
else
{
x=1; y=0;
}
return d;
}
// mod M の逆元を求める
ll mod_inverse(ll a, int M) {
ll x, y;
ll d = extgcd(a, (ll)M, x, y);
assert(d == 1);
return (M + x%M) % M;
}
class NFactorialModM {
public:
void solve(void) {
int T;
cin>>T;
//
// N >= M なら N*(N-1)*...*(M+1)*M*(M-1)*...*1 = 0 mod M
// N < M としてよい ~~
//
// M-N <= 10^5 より
// (M-1)!/N! = (M-1)*...*(N+1) は O(10^5) で計算可能
//
// N! = N!/(M-1)! * (M-1)! = (M-1)! * ((M-1)!/N!)^(-1) であることに留意する。
//
// * M が素数のときウィルソンの定理より
// (M-1)! == (M-1) mod M
//
// * M が合成数のとき M = (M/p) * p (pは素数) とかける
// A. M/p <= N && p != M/p ならば N! で M が現れるので 0
// B. M/p > N ならば M > p*N >= 2*N なので 10^5 > M-N > N (N! 計算すればよい)
// C. M == p^2 のとき
// * p < 2*p <= N なら N! = 0 (mod M)
// * p <= N < 2*p < 2*sqrt(M) < 10^5 のときは (B) として計算できる
//
REP(t,T)
{
int N,M;
cin>>N>>M;
if (N >= M || M == 1)
{
cout<<0<<endl;
continue;
}
ll p;
for (p = 2; p*p <= M; ++p)
{
if (M%p==0)
break;
}
if (p*p > M) // M is prime
{
ll a = 1;
for (int i = 1; i < M-N; ++i)
(a *= (N+i)) %= M;
cout<<(mod_inverse(a,M)*(M-1))%M<<endl;
continue;
}
if (M/p <= N && M != p*p)
{
cout<<0<<endl;
continue;
}
if (p*p == M && 2*p <= N)
{
cout<<0<<endl;
continue;
}
ll a = 1;
for (int i = 1; i <= N; ++i)
(a *= i) %= M;
cout<<a<<endl;
}
}
};
#if 1
int main(int argc, char *argv[])
{
ios::sync_with_stdio(false);
auto obj = new NFactorialModM();
obj->solve();
delete obj;
return 0;
}
#endif
codershifth