結果
問題 | No.575 n! / m / m / m... |
ユーザー |
![]() |
提出日時 | 2019-04-04 21:37:26 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 25 ms / 2,000 ms |
コード長 | 3,299 bytes |
コンパイル時間 | 2,618 ms |
コンパイル使用メモリ | 179,920 KB |
実行使用メモリ | 5,596 KB |
最終ジャッジ日時 | 2024-12-26 08:01:43 |
合計ジャッジ時間 | 4,358 ms |
ジャッジサーバーID (参考情報) |
judge1 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 23 |
ソースコード
#include "bits/stdc++.h"using namespace std;#ifdef _DEBUG#include "dump.hpp"#else#define dump(...)#endif//#define int long long#define rep(i,a,b) for(int i=(a);i<(b);i++)#define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--)#define all(c) begin(c),end(c)const int INF = sizeof(int) == sizeof(long long) ? 0x3f3f3f3f3f3f3f3fLL : 0x3f3f3f3f;const int MOD = 1'000'000'007;template<class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }template<class T> bool chmin(T &a, const T &b) { if (b < a) { a = b; return true; } return false; }// 階乗の対数表現// スターリングの近似を用いて// ln n! を O(log()の計算量) で近似して計算できる// 整数部 x と小数部 y に分けると、n! = y e^x として表せる// ただしそれを計算しようとすると容易にオーバーフローする// n が小さければ愚直に計算するconst double PI = acos(-1);double logFactorial(long long n) {if (n < 100) {double ret = 0;for (long long i = 1; i <= n; i++)ret += log(i);return ret;}return n * log(n) - n + log(2.0 * PI * n) / 2.0 + 1.0 / (12.0 * n);}template<typename T>struct PrimeFactorization {T max_n;vector<bool> is_prime;vector<T> primes;// 前処理PrimeFactorization(T max_n) :max_n(max_n) {T s = sqrt(max_n);is_prime.assign(s + 1, true);is_prime[0] = is_prime[1] = false;for (T i = 2; i*i <= s; i++) {if (!is_prime[i])continue;for (T j = i * i; j <= s; j += i)is_prime[j] = false;}for (T i = 0; i <= s; i++)if (is_prime[i])primes.emplace_back(i);}// 素因数を指数個分並べて昇順で返す// √n以下の素数に対して割り切れるか調べるvector<T> factorize(T n) {assert(n >= 2);vector<T> factors;for (auto &p : primes) {while (n%p == 0) {n /= p;factors.push_back(p);}}if (n != 1)factors.push_back(n);return factors;}// 素因数とその指数のペアを昇順で返すvector<pair<T, int>> factorizeCount(T n) {assert(n >= 2);vector<pair<T, int>> ret;for (auto &p : primes) {int cnt = 0;while (n%p == 0) {n /= p;cnt++;}if (cnt > 0)ret.emplace_back(p, cnt);}if (n != 1)ret.emplace_back(n, 1);return ret;}};// ルジャンドルの公式// n! を素因数 p で最大何回割り切れるかlong long largestPowerPrime(long long n, long long p) {assert(p >= 2);long long ret = 0;long long q = p;while (q <= n) {ret += n / q;q *= p;}return ret;}// n! を m で最大何回割り切れるかlong long largestPowerComposite(long long n, long long m) {assert(m >= 2);PrimeFactorization<long long> pf(n);auto res = pf.factorizeCount(m);long long d = LLONG_MAX;for (auto r : res) {long long c = largestPowerPrime(n, r.first);d = min(d, c / r.second);}return d;}signed main() {cin.tie(0);ios::sync_with_stdio(false);long long n, m; cin >> n >> m;cout << fixed << setprecision(10);PrimeFactorization<long long> pf(n);auto factors = pf.factorize(m);long long d = largestPowerComposite(n, m);double r = (logFactorial(n) - log(m) * d) / log(10);long long x = r;double y = r - x;y = pow(10, y);cout << y << "e" << x << endl;return 0;}