結果

問題 No.2120 場合の数の下8桁
ユーザー 👑 emthrmemthrm
提出日時 2022-11-04 21:37:17
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 1,128 ms / 2,000 ms
コード長 3,421 bytes
コンパイル時間 2,242 ms
コンパイル使用メモリ 206,052 KB
実行使用メモリ 13,840 KB
最終ジャッジ日時 2023-09-25 23:54:21
合計ジャッジ時間 26,915 ms
ジャッジサーバーID
(参考情報)
judge15 / judge13
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1,126 ms
13,596 KB
testcase_01 AC 1,125 ms
13,576 KB
testcase_02 AC 1,124 ms
13,596 KB
testcase_03 AC 1,124 ms
13,560 KB
testcase_04 AC 1,126 ms
13,612 KB
testcase_05 AC 1,123 ms
13,576 KB
testcase_06 AC 1,125 ms
13,708 KB
testcase_07 AC 1,123 ms
13,648 KB
testcase_08 AC 1,124 ms
13,576 KB
testcase_09 AC 1,124 ms
13,636 KB
testcase_10 AC 1,126 ms
13,596 KB
testcase_11 AC 1,124 ms
13,560 KB
testcase_12 AC 1,124 ms
13,592 KB
testcase_13 AC 1,124 ms
13,644 KB
testcase_14 AC 1,123 ms
13,824 KB
testcase_15 AC 1,128 ms
13,840 KB
testcase_16 AC 1,122 ms
13,560 KB
testcase_17 AC 1,124 ms
13,644 KB
testcase_18 AC 1,123 ms
13,504 KB
testcase_19 AC 1,124 ms
13,592 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

// https://ferin-tech.hatenablog.com/entry/2018/01/17/010829
#define __USE_MINGW_ANSI_STDIO 0
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define int ll
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef pair<int, int> PII;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
#define IN(a, b, x) (a<=x&&x<b)
#define PB push_back

const ll LLINF = (1LL<<60);
const int INF = (1LL<<30);
const int MOD = 1000000007;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template<class S,class T>
ostream &operator <<(ostream& out,const pair<S,T>& a){
  out<<'('<<a.first<<','<<a.second<<')';
  return out;
}

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0};

// ax + by = gcd(a, b) となる {x, y, gcd(a, b)} を返す
// O(log(min(a, b)))
ll extgcd(ll a, ll b, ll &x, ll &y) {
  ll g = a; x = 1, y = 0;
  if(b != 0) g = extgcd(b, a%b, y, x), y -= (a/b) * x;
  return g;
}

// a^-1 mod n を返す 存在しなければ-1
// O(log(n))
ll inv(ll a, ll n) {
  ll s, t;
  extgcd(a, n, s, t);
  return (n+s) % n;
}

// 二分累乗法 x^e % mod O(log(e))
ll binpow(ll x, ll e, ll mod) {
  ll a = 1, p = x;
  while(e > 0) {
    if(e%2 == 0) {p = (p*p) % mod; e /= 2;}
    else {a = (a*p) % mod; e--;}
  }
  return a % mod;
}

// x = a1 mod m1, x2 = a2 mod m2 を解く オーバーフローには注意
// O(log(min(m1, m2)))
pair<ll, ll> crt(ll a1, ll a2, ll m1, ll m2) {
  auto normal = [](ll x, ll m) { return x>=-x ? x%m : m-(-x)%m; };
  auto modmul = [&normal](ll a, ll b, ll m) { return normal(a, m)*normal(b, m)%m; };
  ll k1, k2;
  ll g = extgcd(m1, m2, k1, k2);
  if(normal(a1, g) != normal(a2, g)) return {-1, -1};
  ll l = m1 / g * m2;
  ll x = a1 + modmul(modmul((a2-a1)/g, k1, l), m1, l);
  return {x, l};
}

pair<ll, ll> crt(vector<ll> a, vector<ll> m) {
  ll mod = 1, ans = 0;
  int n = a.size();
  REP(i, n) {
    tie(ans, mod) = crt(ans, a[i], mod, m[i]);
    if(ans == -1) return {-1, -1};
  }
  return {ans, mod};
}

ll fact[1000010], ifact[1000010];
void makeFac(ll p, ll q) {
  ll pr = 1;
  REP(i, q) pr *= p;
  fact[0] = ifact[0] = 1;
  FOR(i, 1, pr+1) {
    if(i%p == 0) {
      fact[i] = fact[i-1];
    } else {
      fact[i] = fact[i-1] * i % pr;
    }
    ifact[i] = inv(fact[i], pr);
  }
}

ll C(ll n, ll r, ll p, ll q) {
  if(n < 0 || r < 0 || r > n) return 0;
  // pr = p^q
  int pr = 1;
  REP(i, q) pr *= p;

  ll z = n-r;
  int e0 = 0;
  for(ll u=n/p;u;u/=p) e0 += u;
  for(ll u=r/p;u;u/=p) e0 -= u;
  for(ll u=z/p;u;u/=p) e0 -= u;
  int em = 0;
  for(ll u=n/pr;u;u/=p) em += u;
  for(ll u=r/pr;u;u/=p) em -= u;
  for(ll u=z/pr;u;u/=p) em -= u;

  ll ret = 1;
  while(n > 0) {
    ret = ret*fact[n%pr]%pr*ifact[r%pr]%pr*ifact[z%pr]%pr;
    n /= p; r /= p; z /= p;
  }
  (ret *= binpow(p, e0, pr)) %= pr;
  if(!(p==2 && q >= 3) && em%2) ret = (pr-ret) % pr;
  return ret;
}

ll func(ll n, ll r, ll mod) {
  ll x = mod;
  vector<ll> a, m;
  FOR(i, 2, mod+1) if(x%i == 0) {
    ll cnt=0, pr=1;
    while(x%i==0) x/=i, cnt++, pr*=i;
    makeFac(i, cnt);
    a.PB(C(n, r, i, cnt));
    m.PB(pr);
  }

  return crt(a, m).first;
}

signed main(void)
{
  ll n, m;
  cin >> n >> m;
  const string ans = to_string(func(n, m, 100000000));
  cout << string(8 - ans.length(), '0') << ans << '\n';

  return 0;
}
0