P5400 [CTS2019] 随机立方体

#include <bits/stdc++.h>
#define LL long long
#define int long long
using namespace std;
namespace io {
  const int SIZE = (1 << 19) + 1; char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
  #define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
  inline void flush () {  fwrite (obuf, 1, oS - obuf, stdout); oS = obuf; }
  inline void putc (char x) { *oS ++ = x; if (oS == oT) flush (); }
  template <class I> inline void gi (I &x) { for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1; for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f; }
  string getstr(void) { string s = ""; char c = gc(); while (c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == EOF) c = gc(); while (!(c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == EOF))s.push_back(c), c = gc(); return s;}
  template <class I> inline void print (I x) { if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x; while (x) qu[++ qr] = x % 10 + '0',  x /= 10; while (qr) putc (qu[qr --]); }
  struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io :: gi;  using io :: putc;  using io :: print;
template<class T> bool chkmin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool chkmax(T &a, T b) { return a < b ? (a = b, true) : false; }
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
#define repd(i, l, r) for (int i = (l); i >= (r); i--)
const int N = 7e6, mod = 998244353;
int power(int a,int b) {
  int ans = 1;
  while (b) {  if (b & 1)  ans = ans * a % mod;  b >>= 1;  a = a * a % mod;  }
  return ans;
}
int inv(int x) {  return power(x, mod - 2);  }
int n, m, l, k, f[N], g[N], fac[N], ifac[N];
void init() {
  fac[0] = 1;
  rep (i, 1, N - 1)  fac[i] = fac[i - 1] * i % mod;
  ifac[N - 1] = power(fac[N - 1], mod - 2);
  repd (i, N - 2, 1)  ifac[i] = ifac[i + 1] * (i + 1) % mod;
  ifac[0] = 1;
}
int P(int n,int m) {  return fac[n] * ifac[n - m] % mod;  }
int C(int n,int m) {
  if (n < m)  return 0;
  if (!m || n == m)  return 1;
  return fac[n] * ifac[m] % mod* ifac[n - m] % mod;
}
int hs[N], sh[N];
void pre2(int s) {
  hs[0] = 1;
  rep (i, 1, s)  hs[i] = hs[i - 1] * ((n * m % mod * l % mod -  (n - i) % mod * (m - i) % mod * (l - i) % mod) % mod + mod) % mod; 
  sh[s] = inv(hs[s]);
  repd (i, s - 1, 0)  sh[i] = sh[i + 1] * ((n * m % mod * l % mod - (n - (i + 1)) % mod * (m - (i + 1)) % mod * (l - (i + 1)) % mod) % mod + mod) % mod;
  return ;
}
void solve() {
  gi(n), gi(m), gi(l), gi(k);
  if (n > m)  n ^= m ^= n ^= m;
  if (n > l)  n ^= l ^= n ^= l;
  int qwq = N;  chkmin(qwq, n);  chkmin(qwq, m);  chkmin(qwq, l);
  pre2(qwq);
//  cout << n << " " <<  m << " " << l << " " << k << " " << qwq << "\n";
  int ans = 0;
//  cout << k << " " << qwq
  rep (i, k, qwq) {
    int op = 1;
    if ((i - k) % 2 == 0)  op = 1;
    else op = -1;
    op = op * C(i, k);
    op += mod;  op %= mod;
//    cout << P(n, i) << " " << n << " " << i << "\n";
//    cout << P(n, i) << " " << P(m, i) << " " << P(l, i) << "\n";
    op = op * P(n, i) % mod * P(m, i) % mod * P(l, i) % mod;
    op = op * sh[i] % mod;
    op += mod;  op %= mod;
    ans += op;  ans %= mod;
  }
  print(ans), putc('\n');
//  cout << "qwq\n";
}
signed main () {
#ifdef LOCAL_DEFINE
  freopen("1.in", "r", stdin);
  freopen("1.ans", "w", stdout);
#endif
  init(); 
  int T;  gi(T); 
  while (T--)  solve();
#ifdef LOCAL_DEFINE
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值